为什么我不能使用泛型类型的实例但可以在外面?

时间:2013-06-12 18:33:07

标签: java generics

考虑以下代码

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中的规则如此不同?

3 个答案:

答案 0 :(得分:2)

E extends SomeClass

正如您刚才所写,ESomeClass不同。

您不能将基类型的实例分配给更多派生类型的变量,就像您无法写入一样

Button myButton = new Control();  // Not actually a button!

您可以为E类型的变量分配的唯一内容是E类型的实例。

课外,只有你使用GenericClass<SomeClass>才有效。在那里,E SomeClass

答案 1 :(得分:1)

我认为如果你只是换一个更具体的例子就会很清楚。

假设您将ESomeClass换成了IntegerNumber(请原谅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()); 

这甚至不使用泛型,所以你选择退出泛型类型安全(并获得编译器警告)。