2017-09-27 110 views
0

我有一些接口(和完整性两个虚拟类,所以你可以将代码复制到您的IDE)了解泛型语法 - 泛型类型实现多个接口,参数

public interface ItfA 
{ 
    String getA(); 
} 

public interface ItfB 
{ 
    String getB(); 
} 

public class MyClassAdapter 
{ 
    public Object getValue(Object bean) 
    { 
     return null; // override to do something useful 
    } 
} 

public class MyClass 
{ 
    public MyClass(MyClassAdapter mca) 
    { 
     // do something useful with it 
    } 
} 

而且我有一些功能使用这些作为参数(看起来有点怪异,但是这就是我必须使用他们(我不能改变MyClassAdapter))...

public <T extends ItfA> MyClass getMyClass(final Class<T> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA(); 
      } 
     } 
    ); 
} 

因此,我可以把这个getMyClass只与类实现接口ItfA - 其他人e编译器会抱怨。

或者我也可以重写此方法不指定泛型类型T作为...

public MyClass getMyClass2(final Class<? extends ItfA> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA(); 
      } 
     } 
    ); 
} 

在某些情况下,我需要的类作为实现多个接口参数 - 这将工作:

public <T extends ItfA & ItfB> MyClass getMyOtherClass(final Class<T> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA() + itf.cast(bean).getB(); 
      } 
     } 
    ); 
} 

但这个不起作用

public MyClass getMyOtherClass2(final Class<? extends ItfA & ItfB> itf) 
{ 
    return new MyClass(new MyClassAdapter() 
     { 
      @Override 
      public Object getValue(Object bean) 
      { 
       return itf.cast(bean).getA() + itf.cast(bean).getB(); 
      } 
     } 
    ); 
} 

我不明白的区别betw een这两种通用参数(<T extends ItfA>之前的方法名称和使用Class<T>中的参数与参数中使用Class<? extends ItfA>相反) - 为什么两种类型都使用一个接口,为什么一个接口有两个接口,但另一个接口没有。

任何提示?对我来说,第二个变种更具可读性,所以我更喜欢这一点,但我不明白它与多个接口一起工作...

+0

无法调整'MyClassAdapter'确实可以保证您可以在这里使用泛型获得的功能。无论你在* compile *时间做什么,你都被迫投射。您正在执行的演员*可能会在编译时工作,但可能会在运行时崩溃。 – Makoto

+1

你知道所有的这些都等同于无反射'新MyClass的(新MyClassAdapter(){ @Override 公共 对象的getValue(对象豆) { 回报((ITFA)豆).getA(); } } );',对吗? –

+1

@LouisWasserman:假设有一个''类...... – Makoto

回答

1

TypeParameter不同,TypeArgument不能有几个边界,所以<? extends ItfA & ItfB>无效。

这是我的猜测为什么是这样的。

我认为原因是TypeArgument需要特别有用。例如在Class<T>的情况下,方法cast返回T,您应该能够声明该类型的变量并将结果分配给它。

TypeArgument可以是:

  1. 类类别
  2. InterfaceType
  3. 的TypeVariable
  4. 数组类型
  5. 通配符

例1-4是没有问题的,还有你总是有一些特定类型或类型变量。

如果是通配符,我们有WildcardBounds,例如<? extends IntfA>

如果你只允许一个上限,那么你有一些特定的T。在Class<? extends IntfA>的情况下,您可以假定cast返回InfA

如果你允许更多的上限<? extends ItfA & ItfB>那么问题是,你可以用什么T呢?既然你在一般情况下没有任何特定类型的T,那么你可以做的最好的是Object,这不是很有用。

我认为这是语言作者不能为通配符类型参数指定多个上界的原因。

+0

好的,所以在一种情况下,参数有一个命名类型T(实现ItfA&ItfB),在另一种情况下,参数没有类型。只有一个接口有一个命名类型T(它实现ItfA),或者参数类型ItfA - 好的,这很有道理,谢谢。 – outofmind