13

给定以下界面,

 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);
4

2 回答 2

11

方法上的泛型与类泛型参数无关

您需要在方法上重复它们以使其正确,例如

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>or<? 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 参数更窄。您可以扩大参数范围并缩小参数范围,但不能另辟蹊径。

这就解释了为什么您可以将返回类型(out 参数)从Object更改为 ,Boolean因为任何期望 an 的人Object都会对 a 感到满意Boolean

相反,我们不能扩大返回类型,因为这会给ClassCastException调用该方法并对结果采取行动的任何人提供 a。

方法参数(在参数中)只能扩大。现在方法参数有点复杂,因为 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)

于 2012-10-10T14:20:38.273 回答
5

因为你的类名中的类型参数和方法中的类型参数其实是不同的,你可以在下面做。

   @Override
    public <K, V> Boolean execute(Operation<K, V> operation)
            throws SomeException {
        return false;
    }
于 2012-10-10T14:13:46.833 回答