给出以下界面,
public interface Callback<T> {
<K, V> T execute(Operation<K, V> operation) throws SomeException;
}
如何在operation
类型为Operation<String,String>
的新匿名类中实现该接口
例如,这不会编译:
Callback<Boolean> callback = new Callback<Boolean>() {
@Override
public Boolean execute(Operation<String, String> operation) {
return true;
}
};
executor.execute(callback);
答案 0 :(得分:10)
该方法的泛型与类通用参数无关
你需要在方法上重复它们才能正确,例如
Callback<Boolean> callback = new Callback<Boolean>() {
@Override
public <X,Y> Boolean execute(Operation<X, Y> operation) {
}
};
executor.execute(callback);
换句话说,接口需要一个适用于任何操作参数的执行方法。
如果你想要一个仅适用于特定参数的回调,你需要让它们成为类签名的一部分,例如
public interface Callback<T,K,V> {
T execute(Operation<K, V> operation) throws SomeException;
}
那会让你做到
Callback<Boolean,String,String> callback = new Callback<Boolean,String,String>() {
@Override
public Boolean execute(Operation<String, String> operation) {
}
};
executor.execute(callback);
除非您开始使用可能会限制您太多的<? super K,? super V>
或<? extends K,? extends V>
表单,否则我无法看到获得您想要的内容的路线。
这是您的界面删除的内容
public interface Callback<T> {
T execute(Operation<Object, Object> operation) throws SomeException;
}
然后当您使用T == Boolean
进行实例化时,我们得到
public interface Callback {
Boolean execute(Operation<Object, Object> operation) throws SomeException;
}
无法实现
Boolean execute(Operation<String, String> operation) throws SomeException;
方法作为in参数较窄。您可以扩大参数范围并缩小参数范围,但不能采用其他方式。
这解释了为什么您可以将返回类型(输出参数)从Object
更改为Boolean
,因为任何期望Object
的人都会对Boolean
感到满意。
相反,我们无法扩大返回类型,因为这会给调用方法并对结果起作用的任何人ClassCastException
。
方法参数(在参数中)只能加宽。现在,对于方法参数来说,它有点复杂,因为Java将不同的类型视为不同的方法,因此您可以合法地拥有
public interface Callback<T> {
T execute(Object key, Object value);
}
Callback<Boolean> cb = new Callback<Boolean> {
@Override
public Boolean execute(Object k, Object v) { ... }
// not an @Override
public Boolean execute(String k, String v) { ... }
}
因为第二种方法具有不同的签名。但是,无论是Operation<X,Y>
还是Operation<String,String>
Operation<X,Y>
课程都会被删除为原始类型
你可以做一件事......但它会变得混乱!
public interface StringOperation extends Operation<String,String> {}
然后你可以做
Callback<Boolean> cb = new Callback<Boolean> {
@Override
public <K,V> Boolean execute(Operation<K,V> o) { ... }
// not an @Override
public Boolean execute(StringOperation o) { ... }
}
但请注意,execute(Callback<?>)
方法将调用<K,V> Boolean execute(Operation<K,V> o)
而非Boolean execute(StringOperation o)
答案 1 :(得分:5)
因为类名中的type参数和方法中的type参数实际上是不同的,你可以在下面进行。
@Override
public <K, V> Boolean execute(Operation<K, V> operation)
throws SomeException {
return false;
}