java在匿名类中实现泛型接口 [英] java implement generic interface in an anonymous class

查看:187
本文介绍了java在匿名类中实现泛型接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下接口,

  public interface Callback< T> {
< K,V> T执行(操作< K,V>操作)抛出SomeException;

$ / code>

如何在一个新的匿名类中实现接口,其中 operation 类型为操作< String,String>



不会编译:

 回调<布尔> callback = new Callback< Boolean>(){
@Override
public Boolean execute(操作< String,String>操作){
return true;
}
};
executor.execute(callback);


解决方案

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

您需要在方法上重复它们,例如

 回调<布尔> callback = new Callback< Boolean>(){
@Override
public< X,Y>布尔执行(操作< X,Y>操作){

}
};
executor.execute(callback);

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



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

  public interface Callback< T,K,V> {
T执行(操作< K,V>操作)抛出SomeException;
}

然后让你去做

 回调<布尔,字符串,字符串> callback = new Callback< Boolean,String,String>(){
@Override
public Boolean execute(Operation< String,String> operation){

}
};
executor.execute(callback);

我看不到一条获得您想要的路线......除非您开始使用< ;?超级K,? super V> <?延伸K,?扩展V> 表单,这可能会限制您太多。



以下是您的界面消除的内容

  public interface Callback< T> {
T执行(操作< Object,Object>操作)throws SomeException;
}

然后当你使用 T == Boolean 我们得到

  public interface回调{
布尔执行(操作<对象,对象>操作)抛出SomeException;
}

无法由
$ b执行$ b

 布尔执行(操作< String,String>操作)throws SomeException; 

方法,因为in参数更窄。您可以扩大参数范围并缩小参数,但不能以其他方式进行。

这就解释了为什么你可以将返回类型(输出参数)从 Object 更改为布尔,任何期望 Object 的人都会对布尔值满意。



反过来,我们不能扩大返回类型,因为它会给任何调用方法和作用于结果的人提供一个 ClassCastException p>

方法参数(在参数中)只能加宽。由于Java将不同类型视为不同的方法,所以现在它对于方法参数有些复杂,所以您可以合法地拥有

  public interface Callback< T> {
T execute(Object key,Object value);
}

回拨<布尔> cb =新回调<布尔> {
@Override
public Boolean execute(Object k,Object v){...}
// not a @Override
public Boolean execute(String k,String v) {...}
}

因为第二种方法有不同的签名。但是,无论是操作< String,String> ,您的操作< X,Y> 类都将被擦除为原始类型c $ c>或操作< X,Y>



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

  public interface StringOperation extends Operation< String,String> {} 

然后您可以做

 回调<布尔> cb =新回调<布尔> {
@Override
public< K,V>布尔执行(操作< K,V> o){...}
//不是@Override
public布尔执行(StringOperation o){...}
}

但请记住 execute(Callback<>)方法将调用< K,V>布尔执行(操作< K,V> o)而不是布尔执行(StringOperation o)


Given the following interface,

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

How would I implement the interface in a new anonymous class where operation is of type Operation<String,String>

e.g, this doesn't compile:

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

解决方案

the generics on the method are unrelated to the class generic parameters

you need to repeat them on the method for it to be correct, e.g.

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

        }
};
executor.execute(callback);

In other words the interface requires an execute method that works on any Operation parameters.

If you want a callback that only works on specific parameters you need to make them part of the class signature, e.g.

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

that would then let you do

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

        }
};
executor.execute(callback);

I cannot see a route to getting what you want... unless you start using the <? super K,? super V> or <? extends K,? extends V> forms which may restrict you too much.

Here is what your interface erases to

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

then when you instantiate with T == Boolean we get

 public interface Callback {
    Boolean execute(Operation<Object, Object> operation) throws SomeException;
 }

which cannot be implemented by a

    Boolean execute(Operation<String, String> operation) throws SomeException;

method as the in parameters are narrower. You can widen in parameters and narrow out parameters but you cannot go the other way.

That explains why you can change the return type (out parameter) from Object to Boolean as anyone expecting an Object will be happy with a Boolean.

Conversely we cannot widen the return type as that would give a ClassCastException to anyone calling the method and acting on the result.

The method arguments (in parameters) can only be widened. Now it is somewhat complex for method arguments as Java sees different types as different methods, so you can legally have

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) { ... }
}

because the second method has a different signature. But your Operation<X,Y> class gets erased to just the raw type irrespective of whether it is an Operation<String,String> or Operation<X,Y>

There is one thing you could do... but it gets messy!

public interface StringOperation extends Operation<String,String> {}

then you can do

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

but keep in mind that the execute(Callback<?>) method will be calling <K,V> Boolean execute(Operation<K,V> o) and not Boolean execute(StringOperation o)

这篇关于java在匿名类中实现泛型接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆