Java中遇异常后不终止程序继续执行且无需编写try-catch块的实现方法咨询
嘿,这个需求太实际了——既要拿到所有计算结果,又不想让某个除零异常打断整个流程,还不想写一堆零散的try-catch块。我给你分享几个可行的思路:
方案1:用Optional封装危险计算逻辑
把每个可能抛出异常的操作(比如除法)单独封装成一个返回Optional<Integer>的方法,这样就算计算失败,也只会返回空的Optional,不会抛出异常中断程序。非危险的加减乘可以直接执行,完全不影响流程。
示例代码:
@Test public void testExceptions(int a , int b) { // 封装除法逻辑,仅在内部处理一次异常 Function<Integer, Optional<Integer>> divideByB = num -> { try { return Optional.of(num / b); } catch (ArithmeticException e) { return Optional.empty(); } }; // 执行所有计算,异常的结果会被标记为Optional.empty() Integer c = a + b; Integer d = a * b; Optional<Integer> e = divideByB.apply(a); Integer f = a - b; Optional<Integer> g = c != 0 ? Optional.of(f / c) : Optional.empty(); Optional<Integer> h = g.isPresent() ? Optional.of(g.get() * c) : Optional.empty(); // 输出所有结果,空值可以用默认值或文字标记 System.out.println("c: " + c); System.out.println("d: " + d); System.out.println("e: " + e.orElseGet(() -> -1)); // 用-1标记计算失败 System.out.println("f: " + f); System.out.println("g: " + g.orElse(null)); System.out.println("h: " + h.orElse(null)); System.out.println("this is new Line"); }
核心是把异常处理收拢到一个封装方法里,外部业务代码不用到处写try-catch,单个计算失败也不会阻断后续代码执行。
方案2:用CompletableFuture异步执行每个计算
把每个计算任务放到异步线程中执行,单个任务的异常只会在自己的线程里被处理,不会打断主线程的流程。最后可以统一收集所有任务的结果,不管成功还是失败。
示例代码:
@Test public void testExceptions(int a , int b) { // 异步执行每个计算任务,异常时返回默认值 CompletableFuture<Integer> futureC = CompletableFuture.supplyAsync(() -> a + b); CompletableFuture<Integer> futureD = CompletableFuture.supplyAsync(() -> a * b); CompletableFuture<Integer> futureE = CompletableFuture.supplyAsync(() -> a / b) .exceptionally(ex -> -1); CompletableFuture<Integer> futureF = CompletableFuture.supplyAsync(() -> a - b); // 注意:如果计算有依赖,需要先获取前置结果再执行 Integer f = futureF.join(); Integer c = futureC.join(); CompletableFuture<Integer> futureG = CompletableFuture.supplyAsync(() -> f / c) .exceptionally(ex -> -1); CompletableFuture<Integer> futureH = CompletableFuture.supplyAsync(() -> futureG.join() * c) .exceptionally(ex -> -1); // 收集所有结果 Integer e = futureE.join(); Integer g = futureG.join(); Integer h = futureH.join(); // 输出所有结果 System.out.println("c: " + c); System.out.println("d: " + d); System.out.println("e: " + e); System.out.println("f: " + f); System.out.println("g: " + g); System.out.println("h: " + h); System.out.println("this is new Line"); }
这个方案适合计算之间依赖较弱的场景,还能利用多线程并行提升效率,异常通过exceptionally统一处理,主线程全程不会被中断。
关于你提到的UncaughtExceptionHandler的说明
你代码里设置的Thread.setDefaultUncaughtExceptionHandler其实不会生效——这个Handler只处理线程run方法中未被捕获的异步异常,而你当前的代码是在主线程同步执行的,同步抛出的异常会直接向上传播,根本走不到这个Handler里,所以没法解决你的问题。
总结
如果是同步执行、计算有较强依赖的场景,方案1(Optional封装)更直接简洁;如果计算可以并行、想利用多线程提升效率,方案2(CompletableFuture)更合适。两种方案都不用在业务代码里零散写try-catch,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Argo Triwidodo

