Poniższy kod ilustruje przypadek, w którym sprawdzony wyjątek ExecutionException
jest zgłaszany przez operację, a Clojure otacza go za pomocą RuntimeException
.
Dlaczego Clojure to robi? Czy to normalne? Wydaje się, że Clojure robi coś innego niż Java w tym przypadku. Jaki jest idiomatyczny sposób obsługi faktycznego wyjątku, w tym przypadku Exception
, który spowodował awarię?
user=> (def f (future (Thread/sleep 10000) (throw (Exception. "hello world"))))
#'user/f
user=> (.get f)
Exception hello world user/fn--318 (NO_SOURCE_FILE:81)
user=> (.printStackTrace *e)
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.Exception: hello world
at clojure.lang.Util.runtimeException(Util.java:165)
at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:97)
at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:316)
at user$eval320.invoke(NO_SOURCE_FILE:82)
at clojure.lang.Compiler.eval(Compiler.java:6465)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clojure.main$repl$read_eval_print__5967.invoke(main.clj:244)
at clojure.main$repl$fn__5972.invoke(main.clj:265)
at clojure.main$repl.doInvoke(main.clj:265)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.main$repl_opt.invoke(main.clj:331)
at clojure.main$main.doInvoke(main.clj:427)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.Var.applyTo(Var.java:518)
at clojure.main.main(main.java:37)
Caused by: java.util.concurrent.ExecutionException: java.lang.Exception: hello world
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at clojure.core$future_call$reify__5684.get(core.clj:6064)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:92)
... 16 more
Caused by: java.lang.Exception: hello world
at user$fn__318.invoke(NO_SOURCE_FILE:81)
nil
at clojure.core$binding_conveyor_fn$fn__3713.invoke(core.clj:1817)
at clojure.lang.AFn.call(AFn.java:18)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
2 odpowiedzi
Zgodnie z tym linkiem wydaje się, że clojure nie rzuca sprawdzonych wyjątków, więc zakładam, że clojure łapie to, co może zostać rzucone i zawija: http://dev.clojure.org/display/doc/1.3
Jeśli chodzi o obsługę tego idiomatycznie(?) w Javie, to nadal obowiązują stare zasady. Sprawdziłbym, czy wyjątek opakowany w ExecutionException był jednym ze sprawdzonych wyjątków, o których się spodziewałem, i poradziłby sobie z nimi tak, jak zrobiłbym to w innych okolicznościach (czytaj: emuluj wymuszony przez kompilator try catch). Gdyby tak nie było, albo owinąłbym go w wyjątek środowiska uruchomieniowego i wyrzuciłbym go ponownie, albo zalogowałbym i połknąłbym go w zależności od sytuacji.
Zwróć uwagę, że rzeczywiście wyrzucany jest wyjątek ExcecutionException — po prostu wyjątek jest przechwytywany i obsługiwany przez Clojure.
Clojure zapakuje pewne wyjątki w RuntimeException, gdy je obsłuży — uważam, że ma to na celu uniknięcie konieczności obsługi zaznaczonych wyjątków w kodzie źródłowym Clojure.
Jeśli chcesz uzyskać dostęp do podstawowego wyjątku, (.getCause e)
powinno działać.
Podobne pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].