java在匿名类中实现泛型接口

use*_*096 11 java generics

鉴于以下界面,

 public interface Callback<T> {
    <K, V> T execute(Operation<K, V> operation) throws SomeException;
 }
Run Code Online (Sandbox Code Playgroud)

我如何在一个operation类型为的新匿名类中实现该接口Operation<String,String>

例如,这不编译:

 Callback<Boolean> callback = new Callback<Boolean>() {
        @Override
        public Boolean execute(Operation<String, String> operation) {
              return true;
        }
 };
 executor.execute(callback);
Run Code Online (Sandbox Code Playgroud)

Ste*_*lly 10

方法的泛型与类通用参数无关

你需要在方法上重复它们才能使它正确,例如

Callback<Boolean> callback = new Callback<Boolean>() {
        @Override
        public <X,Y> Boolean execute(Operation<X, Y> operation) {

        }
};
executor.execute(callback);
Run Code Online (Sandbox Code Playgroud)

换句话说,接口需要一个适用于任何Operation参数的execute方法.

如果你想要一个仅适用于特定参数的回调,你需要让它们成为类签名的一部分,例如

 public interface Callback<T,K,V> {
    T execute(Operation<K, V> operation) throws SomeException;
 }
Run Code Online (Sandbox Code Playgroud)

然后会让你这样做

Callback<Boolean,String,String> callback = new Callback<Boolean,String,String>() {
        @Override
        public Boolean execute(Operation<String, String> operation) {

        }
};
executor.execute(callback);
Run Code Online (Sandbox Code Playgroud)

我看不到,这是让你想要的...的路线,除非你开始使用<? super K,? super V><? extends K,? extends V>可能限制你太多的形式.

这是您的界面擦除的内容

 public interface Callback<T> {
    T execute(Operation<Object, Object> operation) throws SomeException;
 }
Run Code Online (Sandbox Code Playgroud)

然后当你实例化T == Boolean我们得到

 public interface Callback {
    Boolean execute(Operation<Object, Object> operation) throws SomeException;
 }
Run Code Online (Sandbox Code Playgroud)

一个不能实现的

    Boolean execute(Operation<String, String> operation) throws SomeException;
Run Code Online (Sandbox Code Playgroud)

in参数的方法较窄.您可以扩大参数范围并缩小参数范围,但不能采用其他方式.

这就解释了为什么你可以改变返回类型(输出参数)Object,Boolean因为任何人都期望Object会对a感到满意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) { ... }
}
Run Code Online (Sandbox Code Playgroud)

因为第二种方法有不同的签名.但是,你的Operation<X,Y>类被擦除,只是原始类型不管它是一个Operation<String,String>Operation<X,Y>

你可以做一件事......但它会变得混乱!

public interface StringOperation extends Operation<String,String> {}
Run Code Online (Sandbox Code Playgroud)

那么你可以做到

Callback<Boolean> cb = new Callback<Boolean> {
  @Override
  public <K,V> Boolean execute(Operation<K,V> o) { ... }
  // not an @Override
  public Boolean execute(StringOperation o) { ... }
}
Run Code Online (Sandbox Code Playgroud)

但请记住,该execute(Callback<?>)方法将调用<K,V> Boolean execute(Operation<K,V> o)而不是Boolean execute(StringOperation o)


Ami*_*nde 5

因为类名中的type参数和方法中的type参数实际上是不同的,您可以在下面执行.

   @Override
    public <K, V> Boolean execute(Operation<K, V> operation)
            throws SomeException {
        return false;
    }
Run Code Online (Sandbox Code Playgroud)