java 在匿名类中实现通用接口

2022-09-04 02:52:07

给定以下接口,

 public interface Callback<T> {
    <K, V> T execute(Operation<K, V> operation) throws SomeException;
 }

如何在一个新的匿名类中实现接口,其中 is 类型operationOperation<String,String>

例如,这不会编译:

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

答案 1

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

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

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 参数较窄。您可以加宽参数和缩小参数范围,但不能走另一条路。

这就解释了为什么您可以将返回类型(out 参数)从 更改为,因为任何期望的人都对 .ObjectBooleanObjectBoolean

相反,我们不能扩大返回类型,因为这会给调用方法并对结果采取行动的任何人提供。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) { ... }
}

因为第二种方法具有不同的签名。但是,您的类将被擦除为原始类型,而不管它是 orOperation<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)


答案 2

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

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

推荐