考虑以下代码
class SomeClass {
}
class GenericsExample<E extends SomeClass> {
public void createError() {
process(new SomeClass()); //Compiler error!
}
public void createWorking() {
E some = new SomeClass(); //Compiler error!
process(some);
}
public void process(E object) {
}
}
public class Sandbox {
public void run() {
new GenericsExample<SomeClass>().process(new SomeClass()); //Not a compiler error?!
new GenericsExample().process(new SomeClass()); //Still not a compiler error?!
}
}
第一个错误的消息(第二个错误基本相同)
required: E
found: SomeClass
reason: actual argument SomeClass cannot be converted to E by method invocation conversion
where E is a type-variable:
E extends SomeClass declared in class GenericsExample
这可以通过将SomeClass强制转换为E来修复,但我为什么要这样做?如果一个方法将E作为参数并且E扩展SomeClass,那么它不应该接受SomeClass作为参数吗?为什么这是编译器错误而不是警告?
为什么这不适用于外部类,即使在我甚至没有声明泛型类型的情况下呢?为什么GenericsExample与Sandbox中的规则如此不同?
答案 0 :(得分:2)
E extends SomeClass
正如您刚才所写,E
与SomeClass
不同。
您不能将基类型的实例分配给更多派生类型的变量,就像您无法写入一样
Button myButton = new Control(); // Not actually a button!
您可以为E
类型的变量分配的唯一内容是E
类型的实例。
课外,只有你使用GenericClass<SomeClass>
才有效。在那里,E
是 SomeClass
。
答案 1 :(得分:1)
我认为如果你只是换一个更具体的例子就会很清楚。
假设您将E
和SomeClass
换成了Integer
和Number
(请原谅Exte而不是工具)来获取Integer extends Number
。在这种情况下,很明显您无法执行以下操作
Integer i = new Number();
因为Integer比Number更具体。
答案 2 :(得分:0)
为什么这不适用于外部类,即使在我甚至没有声明泛型类型的情况下呢?
因为那些是不同的情况:
new GenericsExample<SomeClass>().process(new SomeClass());
这不是编译器错误,因为在这里,双方都有SomeClass
,不是 E extends SomeClass
。
new GenericsExample().process(new SomeClass());
这甚至不使用泛型,所以你选择退出泛型类型安全(并获得编译器警告)。