Java 8供应商异常处理 [英] Java 8 Supplier Exception handling

查看:541
本文介绍了Java 8供应商异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码 -

  public class TestCompletableFuture {

BiConsumer< Integer,Throwable> biConsumer =(x,y) - > {
System.out.println(x);
System.out.println(y);
};

public static void main(String args []){
TestCompletableFuture testF = new TestCompletableFuture();
testF.start();
}

public void start(){
Supplier< Integer> numberSupplier = new Supplier< Integer>(){
@Override
public Integer get(){
return SupplyNumbers.sendNumbers();
}
};
CompletableFuture< Integer> testFuture = CompletableFuture.supplyAsync(numberSupplier).whenComplete(biConsumer);
}
}

class SupplyNumbers {
public static Integer sendNumbers(){
return 25; //只是为了工作的缘故,它不正确。
}
}

以上事情运行正常。但是,在我的情况下, sendNumbers 也可能会抛出异常。喜欢 -

  class SupplyNumbers {
public static Integer sendNumbers()throws Exception {
return 25; //只是为了工作的缘故,它不正确。
}
}

现在我想处理这个异常为'y'在我的 biConsumer 中。这将有助于我处理单个函数中的结果以及异常(如果有的话)( biConsumer )。



<任何想法?我可以在这里使用 CompletableFuture.exceptionally(fn)

解决方案

p>当您要处理检查的异常时,使用标准功能界面的工厂方法无效。当您将代码捕获到lambda表达式中时,您有问题,即catch子句需要 CompletableFuture 实例来设置异常,而工厂方法需要供应商,鸡和蛋。



您可以使用类的实例字段在创建后允许突变,但是最后,由此产生的代码并不干净,而且更为复杂,因此直接执行 Executor 的解决方案。 CompletableFuture 说:



所以你知道下面的代码会显示 CompletableFuture.supplyAsync(Supplier)的标准行为,同时处理检查的异常直接:

  CompletableFuture< Integer> f = new CompletableFuture<>(); 
ForkJoinPool.commonPool()。submit(() - > {
try {f.complete(SupplyNumbers.sendNumbers());}
catch(Exception ex){f.completeExceptionally ex);}
});

文档还说:


...为了简化监控,调试和跟踪,所有生成的异步任务都是标记接口的实例 CompletableFuture.AsynchronousCompletionTask


如果要遵守此惯例,使解决方案更像原始的 supplyAsync 方法,请将代码更改为:

  CompletableFuture< Integer> f = new CompletableFuture<>(); 
ForkJoinPool.commonPool()。submit(
(Runnable& CompletableFuture.AsynchronousCompletionTask)() - > {
try {f.complete(SupplyNumbers.sendNumbers());}
catch(Exception ex){f.completeExceptionally(ex);}
});


Consider the following code -

public class TestCompletableFuture {

    BiConsumer<Integer, Throwable> biConsumer = (x,y) -> {
        System.out.println(x);
        System.out.println(y);
    };

    public static void main(String args[]) {
        TestCompletableFuture testF = new TestCompletableFuture();
        testF.start();      
    }

    public void start() {
        Supplier<Integer> numberSupplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                return SupplyNumbers.sendNumbers();                     
            }
        };
        CompletableFuture<Integer> testFuture = CompletableFuture.supplyAsync(numberSupplier).whenComplete(biConsumer);         
    }       
}

class SupplyNumbers {
    public static Integer sendNumbers(){
        return 25; // just for working sake its not  correct.
    }
}

The above thing works fine. However sendNumbers could also throw an exception in my case. Like -

class SupplyNumbers {
    public static Integer sendNumbers() throws Exception {
        return 25; // just for working sake its not  correct.
    }
}

Now I want to handle this exception as 'y' in my biConsumer. This will help me in handling the result as well as exception (if any) inside a single function (biConsumer).

Any ideas? Can I use CompletableFuture.exceptionally(fn) here or anything else?

解决方案

The factory methods using the standard functional interfaces aren’t helpful when you want to handle checked exceptions. When you insert code catching the exception into the lambda expression, you have the problem that the catch clause needs the CompletableFuture instance to set the exception while the factory method needs the Supplier, chicken-and-egg.

You could use an instance field of a class to allow mutation after creation, but in the end, the resulting code isn’t clean and more complicated that a straight-forward Executor-based solution. The documentation of CompletableFuture says:

so you know the following code will show the standard behavior of CompletableFuture.supplyAsync(Supplier) while handling checked exceptions straight-forward:

CompletableFuture<Integer> f=new CompletableFuture<>();
ForkJoinPool.commonPool().submit(()-> {
  try { f.complete(SupplyNumbers.sendNumbers()); }
  catch(Exception ex) { f.completeExceptionally(ex); }
});

The documentation also says:

… To simplify monitoring, debugging, and tracking, all generated asynchronous tasks are instances of the marker interface CompletableFuture.AsynchronousCompletionTask.

If you want to adhere to this convention to make the solution even more behaving like the original supplyAsync method, change the code to:

CompletableFuture<Integer> f=new CompletableFuture<>();
ForkJoinPool.commonPool().submit(
  (Runnable&CompletableFuture.AsynchronousCompletionTask)()-> {
    try { f.complete(SupplyNumbers.sendNumbers()); }
    catch(Exception ex) { f.completeExceptionally(ex); }
});

这篇关于Java 8供应商异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆