我正在创建一个小型应用程序,偶然发现了以下问题。
我的应用程序中有一个collections.Counter
,签名为List<Class<MyCustomBaseClass>>
的函数。
public <T extends MyCustomBaseClass> void addClass(Class<T> clazz)
应该将AddClass
放入列表中。但是我在那里遇到以下错误:
clazz
这是我可以简化的3个班级:
The method add(Class<MyCustomBaseClass>) in the type List<Class<MyCustomBaseClass>> is not applicable for the arguments (Class<T>)
。
// Program.java
package me.mischa.stackoverflow;
import java.util.ArrayList;
import java.util.List;
public class Program {
private List<Class<MyCustomBaseClass>> _listOfClasses;
private static Program _instance;
public Program() {
_listOfClasses = new ArrayList<>();
}
public static void main(String[] args) {
Program program = new Program();
program.addClass(MyCustomChildClass.class);
}
public <T extends MyCustomBaseClass> void addClass(Class<T> clazz) {
_listOfClasses.add(clazz);
}
}
。
// MyCustomBaseClass.java
package me.mischa.stackoverflow;
public class MyCustomBaseClass {
}
错误在第// MyCustomChildClass.java
package me.mischa.stackoverflow;
public class MyCustomChildClass extends MyCustomBaseClass {
}
行
我不明白为什么_listOfClasses.add(clazz);
与<T extends MyCustomBaseClass>
不兼容
答案 0 :(得分:2)
Java的泛型是不变的。这意味着,作为类型参数的Class<MyCustomBaseClass>
完全意味着,不允许表示MyCustomBaseClass
子类的Class对象。
在您的addClass
方法中,您仅在定义T
时给出了上限– T
可以是MyCustomBaseClass
的子类,例如您的班级MyCustomChildClass
。由于不匹配,编译器不允许此调用。
您可以通过提供匹配的上限来扩展_listOfClasses
中的允许范围,这将允许方法addClass
进行编译。
private List<Class<? extends MyCustomBaseClass>> _listOfClasses;
顺便说一句,由于T
中addClass
的类型实际上并不重要,因此您可以删除它并使用通配符。
public void addClass(Class<? extends MyCustomBaseClass> clazz) {
答案 1 :(得分:0)
Java的泛型是不变的。这是有原因的。想象以下代码(注意:showExpr :: Expr -> Expr
showExpr (Node op (SomeOperand a) (SomeOperand b)) = showOperand a ++ show op ++ showOperand b
showExpr (Value i) = show i
是Number
和Integer
的超类型):
Double
在上面的 if 中,如果它已经是有效的Java,则您正在将Integer分配给Double,这是一个问题,因为Integer不是Double。这就是为什么实际上,如果您尝试编译以上内容,将无法正常工作。第二行被标记为无效的Java,因为无法将List<Double> doublesOnly = new ArrayList<Double>();
List<Number> numbers = doublesOnly;
numbers.add(new Integer(5));
Double d = doublesOnly.get(0);
分配给List<Double>
。有一个解决方案:
List<Number>
这次,第3行出现错误:除了List<Double> doublesOnly = new ArrayList<Double>();
List<? extends Number> numbers = doublesOnly;
numbers.add(new Integer(5));
Double d = doublesOnly.get(0);
之外,您无法向List<? extends Something>
添加任何内容。无法修复此代码,这很好,因为我们从根本上做不好的事情。
针对您的具体情况,解决方案有两个方面:
通常,您应该避免在API中使用null
的概念。通常,使用工厂代替。
如果必须的话,请尝试以下操作:Class<?>
。是的,扩展了2个。您可以将List<Class<? extends MyCustomBaseClass>>
添加到此列表。