Java 泛型超参数

Java 泛型超参数,java,generics,super,Java,Generics,Super,有人能解释一下为什么下面的代码没有编译,以及是否有编写doubleRequestExecute所需的行为(能够在CallbackFirst尝试中传递)的方法吗 (不起作用,请参见备注) 试着这样做: public static <A extends Entity, B extends Entity> void doubleRequestExecute(Request<A> request1, Request<B> request2, final

有人能解释一下为什么下面的代码没有编译,以及是否有编写doubleRequestExecute所需的行为(能够在
CallbackFirst尝试中传递)的方法吗
(不起作用,请参见备注)

试着这样做:

public static <A extends Entity, B extends Entity>
    void doubleRequestExecute(Request<A> request1, Request<B> request2,
    final Callback<Pair<? super A, ? super B>> callback)
...
callback.onSuccess(new Pair<A, B>(result, result2.value));
...
如何实例化
l
?它是一个列表,由
整数
限定的内容组成

List<List<? super Integer>> l = new ArrayList<List<Integer>>(); // NO
List<List<? super Integer>> l = new ArrayList<List<Number>>();  // NOPE
List<List<? super Integer>> l = new ArrayList<List<Object>>();  // NEITHER
List<List<? super Integer>> l = new ArrayList<List<? super Integer>>();  // OK

List那么,您正在尝试实现一个工作流join。您希望将一个成对的延续转换为两个组件的延续。我认为在您的实现中存在竞争条件,但暂且不谈,让我们谈谈类型

如果您死心塌地地想让组件类型具有名称,并且与
A
B
不同,那么它们需要是它们的超类(因为您将从各自的请求中获得A和B)。这是您在OP中尝试的。假设
C
D
只能是
实体
,将关系扭转过来,您可以在不允许使用
super
关键字的情况下获得它:

public static < C extends Entity, D extends Entity, A extends C, B extends D > void doubleRequestExecute(
    Request< A > request1, Request< B > request2,
    Callback< Pair< C, D > > callback
) {
    ...
}
如果您愿意使用这样的调用代码(我相信这是模仿@Flavio的回答的):

尤里卡

Java中没有声明时间差异声明这一事实意味着像这样深度嵌套的泛型类型会带来无尽的麻烦。解决方案是使用愚蠢的包装类来强制继承工作

public static class PairCallback< A, B > implements Callback< Pair< A, B > > {
    private final Callback< Pair< A, B > > cbDelegate;
    public PairCallback( Callback< Pair< A, B > > cbDelegate ) {
        this.cbDelegate = cbDelegate;
    }
    public void onSuccess( A a, B b ) {
        onSuccess( new Pair< A, B >( a, b ) );
    }
    @Override public void onSuccess( Pair< A, B > p ) { cbDelegate.onSuccess( p ); }
    @Override public void onFailure( Throwable caught ) { cbDelegate.onFailure( caught ); }
}
public static < A extends Entity, B extends Entity > void doubleRequestExecute(
    Request< A > reqA, Request< B > reqB,
    final PairCallback< ? super A, ? super B > callback
) {
    final Holder< A > result1 = new Holder< A >();
    final Holder< B > result2 = new Holder< B >();
    reqA.execute(new Callback<A>() {
        @Override public void onSuccess(A result) {
            if (result2.value != null) {
                callback.onSuccess(result, result2.value);
            } else {
                result1.value = result;
            }
        }
        @Override public void onFailure(Throwable caught) {
            callback.onFailure(caught);
        }
    });
    reqB.execute(new Callback<B>() {
        @Override public void onSuccess(B result) {
            if (result1.value != null) {
                callback.onSuccess(result1.value, result);
            } else {
                result2.value = result;
            }
        }
        @Override public void onFailure(Throwable caught) {
            callback.onFailure(caught);
        }
    });
}

private static class Entity1 extends Entity {}
private static class Entity2 extends Entity1 {}
public static void main( String... args ) {
    doubleRequestExecute(
        new Request< Entity >(), new Request< Entity >(),
        new PairCallback< Object, Object >( new Callback< Pair< Object, Object > >() {
            @Override public void onSuccess( Pair< Object, Object> result ) {}
            @Override public void onFailure( Throwable caught ) {}
        } )
    );
    doubleRequestExecute(
        new Request< Entity2 >(), new Request< Entity1 >(),
        new PairCallback< Entity1, Entity >( new Callback< Pair< Entity1, Entity > >() {
            @Override public void onSuccess( Pair< Entity1, Entity > result ) {}
            @Override public void onFailure( Throwable caught ) {}
        } )
    );
}
公共静态类PairCallback实现回调>{
私有最终回调>cbDelegate;
公共对回调(回调>cbDelegate){
this.cbDelegate=cbDelegate;
}
成功时公开作废(A、B){
成功(新对(A,B));
}
@在成功时重写公共void(对p){cbDelegate.onSuccess(p);}
@重写公共void onFailure(可丢弃捕获){cbDelegate.onFailure(捕获);}
}
公共静态无效doubleRequestExecute(
请求reqA,请求reqB,
最终配对回拨<?超级A,?超级B>回拨
) {
最终持有人结果1=新持有人();
最终持有人结果2=新持有人();
请求执行(新回调(){
@成功时覆盖公共无效(结果){
if(result2.value!=null){
onSuccess(result,result2.value);
}否则{
结果1.value=结果;
}
}
@失效时覆盖公共无效(可丢弃){
callback.onFailure(捕获);
}
});
要求执行(新回调(){
@成功时覆盖公共无效(B结果){
如果(result1.value!=null){
onSuccess(result1.value,result);
}否则{
结果2.值=结果;
}
}
@失效时覆盖公共无效(可丢弃){
callback.onFailure(捕获);
}
});
}
私有静态类Entity1扩展了实体{}
私有静态类Entity2扩展了Entity1{}
公共静态void main(字符串…参数){
双重请求执行(
新请求<实体>(),新请求<实体>(),
新的PairCallback(新的回调>(){
@成功时重写公共void(对<对象,对象>结果){}
@重写公共void onFailure(可丢弃捕获){
} )
);
双重请求执行(
新请求(),新请求(),
新的PairCallback(新回调>(){
@成功时重写公共void(对result){
@重写公共void onFailure(可丢弃捕获){
} )
);
}

我将投票表决你的问题,因为它是多么具有挑战性和相关性。

类型参数没有下限。事实上-只有通配符可以使用
super
。明白为什么吗?我知道在大多数情况下,这根本没有用(由于任何东西都可能衰变为超越一切的物体,因此可能使用得非常错误),但在这种情况下,它似乎有一个有效的用途,而且由于任意的语言限制,根本不可能做我想做的事情。我很好奇为什么这个问题被否决了。在我看来,这是一个完全合理的做法,而语言似乎不支持它(或者至少还没有人提供有效的方法)。这是我尝试的第一件事,但很快就失败了。调用时,编译失败,出现以下错误
没有类型变量的实例A,B的存在使得参数类型符合形式参数类型CallbackFurthermore,即使它超过了这一点,
Pair
也无法转换为
pairy。你是对的,我做了一些更正。不过,不要问我为什么它会起作用,我不能完全理解这一点。不幸的是,它仍然不起作用,目标是得到
Callback我想我正在做你需要的:
Pair
不可分配给
Pair
,就像
List
不可分配给
List
,所以你不能为
Pair
实例提供
回调
。答案更新。至于线程安全,实际的代码保证所有处理程序都是安全的在同一个线程上执行,因此没有竞争(应该提到)。不幸的是,这两种解决方案都不充分。第一种解决方案,除了没有真正解决手头的问题之外,甚至不可能,因为类型为?super Pair的对象不可能被实例化(它仍然需要A和B,而不是任何超级对象).第二个解决方案很接近,但C和D不一定需要扩展实体(只需要请求类型参数),例如
Callbackpublic static <A extends Entity, B extends Entity> void doubleRequestExecute(Request<A> request1, Request<B> request2,
        final Callback<? super Pair<? extends A, ? extends B>> callback) { ... }
private static final class E1 extends Entity { }
private static final class E2 extends Entity { }

public static void main(String[] args) {
    Request<E1> r1 = null;
    Request<E2> r2 = null;
    // This is the callback you try to define in your comment
    Callback<Pair<? extends Entity, ? extends Entity>> cb = null; 
    // This is another option
    Callback<Object> cb2 = null;
    // Further option mentioned in comments
    Callback<Pair<? extends Object, ? extends Object>> cb3 = null;
    doubleRequestExecute(r1, r2, cb);
    doubleRequestExecute(r1, r2, cb2);
    doubleRequestExecute(r1, r2, cb3);
}
Pair<Integer, Integer> pII = new Pair<Integer, Integer>();
Pair<Object, Object> pOO = pII; // Compile error
pOO.setFirst("Whoa");
Integer i = pII.getFirst();
List<List<? super Integer>> l = null; // TODO
l.add(new ArrayList<Integer>());
l.add(new ArrayList<Number>());
l.add(new ArrayList<Objec>());
List<List<? super Integer>> l = new ArrayList<List<Integer>>(); // NO
List<List<? super Integer>> l = new ArrayList<List<Number>>();  // NOPE
List<List<? super Integer>> l = new ArrayList<List<Object>>();  // NEITHER
List<List<? super Integer>> l = new ArrayList<List<? super Integer>>();  // OK
// Only possible declaration
Callback<Pair<? super E1, ? super E2>> cb = new Callback<Pair<? super E1, ? super E2>>() {
...
}
doubleRequestExecute(new Request<E1>(), new Request<E2>(),
        new Callback<Pair<? extends Object, ? extends Object>>() {
          @Override public void onSuccess(Pair<? extends Object, ? extends Object> result) {}
          @Override public void onFailure(Throwable caught) {}
        });
public static < C extends Entity, D extends Entity, A extends C, B extends D > void doubleRequestExecute(
    Request< A > request1, Request< B > request2,
    Callback< Pair< C, D > > callback
) {
    ...
}
public static < A extends Entity, B extends Entity > void doubleRequestExecute(
    Request< A > request1, Request< B > request2,
    Callback< ? super Pair< A, B > > callback
) {
    // change all Cs to As and Ds to Bs in the original code 
}
doubleRequestExecute(
    new Request<Entity>(), new Request<Entity>(),
    new Callback< Pair< ?, ? > >() {
        @Override public void onSuccess(Pair< ?, ? > result) {}
        @Override public void onFailure(Throwable caught) {}
    }
);
public static < C, D > void doubleRequestExecute(
    Request< ? extends C > reqA, Request< ? extends D > reqB,
    final Callback< Pair< C, D > > callback
) {
    // change all As to Cs and Bs to Ds in the original code 
}
doubleRequestExecute(
    new Request<Entity>(), new Request<Entity>(),
    new Callback< Pair< Object, Object > >() {
        @Override public void onSuccess(Pair< Object, Object > result) {}
        @Override public void onFailure(Throwable caught) {}
    }
);
public static class PairCallback< A, B > implements Callback< Pair< A, B > > {
    private final Callback< Pair< A, B > > cbDelegate;
    public PairCallback( Callback< Pair< A, B > > cbDelegate ) {
        this.cbDelegate = cbDelegate;
    }
    public void onSuccess( A a, B b ) {
        onSuccess( new Pair< A, B >( a, b ) );
    }
    @Override public void onSuccess( Pair< A, B > p ) { cbDelegate.onSuccess( p ); }
    @Override public void onFailure( Throwable caught ) { cbDelegate.onFailure( caught ); }
}
public static < A extends Entity, B extends Entity > void doubleRequestExecute(
    Request< A > reqA, Request< B > reqB,
    final PairCallback< ? super A, ? super B > callback
) {
    final Holder< A > result1 = new Holder< A >();
    final Holder< B > result2 = new Holder< B >();
    reqA.execute(new Callback<A>() {
        @Override public void onSuccess(A result) {
            if (result2.value != null) {
                callback.onSuccess(result, result2.value);
            } else {
                result1.value = result;
            }
        }
        @Override public void onFailure(Throwable caught) {
            callback.onFailure(caught);
        }
    });
    reqB.execute(new Callback<B>() {
        @Override public void onSuccess(B result) {
            if (result1.value != null) {
                callback.onSuccess(result1.value, result);
            } else {
                result2.value = result;
            }
        }
        @Override public void onFailure(Throwable caught) {
            callback.onFailure(caught);
        }
    });
}

private static class Entity1 extends Entity {}
private static class Entity2 extends Entity1 {}
public static void main( String... args ) {
    doubleRequestExecute(
        new Request< Entity >(), new Request< Entity >(),
        new PairCallback< Object, Object >( new Callback< Pair< Object, Object > >() {
            @Override public void onSuccess( Pair< Object, Object> result ) {}
            @Override public void onFailure( Throwable caught ) {}
        } )
    );
    doubleRequestExecute(
        new Request< Entity2 >(), new Request< Entity1 >(),
        new PairCallback< Entity1, Entity >( new Callback< Pair< Entity1, Entity > >() {
            @Override public void onSuccess( Pair< Entity1, Entity > result ) {}
            @Override public void onFailure( Throwable caught ) {}
        } )
    );
}