Java 正确覆盖CompletableFuture.cancel

Java 正确覆盖CompletableFuture.cancel,java,completable-future,Java,Completable Future,我注意到,如果将来调用thenApply,则重写cancel方法不会生效。派生的未来不知道原始版本有这样一个覆盖的事实。下面的代码演示了这个问题 是否有任何方法可以正确地覆盖该方法而不丧失改变未来的可能性 import java.util.concurrent.CompletableFuture; 公共班机{ 公共静态void main(字符串[]args){ CompletableFuture未修改=新建CompletableFuture(){ @凌驾 公共布尔值取消(布尔值可能中断刷新){

我注意到,如果将来调用
thenApply
,则重写
cancel
方法不会生效。派生的未来不知道原始版本有这样一个覆盖的事实。下面的代码演示了这个问题

是否有任何方法可以正确地覆盖该方法而不丧失改变未来的可能性

import java.util.concurrent.CompletableFuture;
公共班机{
公共静态void main(字符串[]args){
CompletableFuture未修改=新建CompletableFuture(){
@凌驾
公共布尔值取消(布尔值可能中断刷新){
System.out.println(“--->取消未修改”);
返回super.cancel(可能中断frunning);
}
};
未修改
.取消(真);
CompletableFuture modified=新的CompletableFuture(){
@凌驾
公共布尔值取消(布尔值可能中断刷新){
System.out.println(“--->取消修改”);
返回super.cancel(可能中断frunning);
}
};
未修改
。然后应用(x->x)
.取消(真);
System.out.println(“--->结束”);
}
//输出
//>任务:Main.Main()
//--->取消未修改的
//结束
}

没有直接的方法来做你想做的事情,因为
然后apply
返回一个新的
CompletableFuture
对象。
但是,如果确实需要这样做,可以尝试重写
CompletableFuture
类本身

让我解释一下!
CompletableFuture。然后apply()
方法进一步调用
CompletableFuture
类的
uniApplyStage
私有方法,在该类中创建要返回的
新CompletableFuture()
实例。(我反编译了Java源代码以检查这一点。)

无法重写此方法,因为它是私有方法。但是,如果你,

  • 反编译类
    CompletableFuture
  • 复制代码
  • 在创建新的CompletableFuture()实例时,将
    uniApplyStage
    方法更改为
    @Override
    cancel方法
  • 然后在运行时,按照中提到的步骤使用“自定义类加载器”在运行时重新加载类
  • 从理论上讲,你应该能够做到这一切

    但当然,问题依然存在。你有多想这么做D


    根据我的诚实意见,把这个答案看作是最后的选择。 您需要Java 9或更高版本。然后,所有创建新的依赖未来的方法都将调用工厂方法
    newIncompleteFuture()
    ,您可以覆盖该方法:

    public static void main(String arg[]) {
        class MyFuture<T> extends CompletableFuture<T> {
            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                System.out.println("customized cancel");
                return super.cancel(mayInterruptIfRunning);
            }
    
            @Override
            public <U> CompletableFuture<U> newIncompleteFuture() {
                return new MyFuture<>();
            }
        }
        MyFuture<Object> future = new MyFuture<>();
    
        System.out.print("direct: ");
        future.cancel(true);
    
        System.out.print("indirect: ");
        future.thenApply(x -> x).cancel(true);
    
        System.out.print("even longer chain: ");
        future.thenApply(x -> x).exceptionally(t -> null).cancel(true);
    
        System.out.println("end");
    }
    

    但请记住,对于
    CompletableFuture
    ,取消与带有
    CancellationException
    的异常完成并无区别。因此,有人可以异常调用
    completeeexception(new CancellationException())
    而不是
    cancel(…)
    ,达到相同的效果。

    因为
    然后apply
    返回一个新的
    CompletionStage
    ,这似乎不太可能。