为什么我不能将原始类型分配给参数化类型? (JAVA)

时间:2013-12-26 20:20:11

标签: java generics types

如果将参数化类型对象分配给原始类型对象,据我所知,原始类型对象采用参数化类型。这对我来说很有意义。但为什么它不能相反呢?我认为在将Raw Type分配给Paramterized Type之后,编译器将简单地假设参数化类型。

感谢您的帮助!

好吧,据我所知,以下内容没有问题,将Raw Type视为传递了String类型:

SomeClass<String> instance1 = new SomeClass<>();
SomeClass instance2 = instance1;

但是以下内容会抛出警告,并且任何类的方法都不会隐含一种String类型:

SomeClass instance1 = new SomeClass();
SomeClass<String> instance2 = instance1;

我想我只想弄明白,所以如果是这样,我很遗憾浪费每个人的时间。这是否有效,因为instance2正在创建一个指针而不是一个新对象,并且一个指针不能改变它所指向的对象的行为?

1 个答案:

答案 0 :(得分:5)

泛型只是编译时间。基本上,当编译代码时,参数化类型将被删除并替换为强制转换。

考虑以下内容:

class SomeClass<T> {
    T value;

    T get() {
        return value;
    }

    void set(T val) {
        value = val;
    }
}

当您声明一个新的SomeClass<String>时,看起来会发生的事情是这样的:

class SomeClass {
    String value; // "value is now a String"

    String get() {
        return value;
    }

    void set(String val) {
        value = val;
    }
}

但事实并非如此。实际发生的是SomeClass总是这样:

class SomeClass {
    Object value; // erasure of T is Object

    Object get() {
        return value;
    }

    void set(Object val) {
        value = val;
    }
}

当你有一个SomeClass<String>时,只要你说String someString = someClass.get();,编译器就会从Object转换为String。在运行时,原始时间和参数化类型之间没有行为差异,只有是否存在强制转换。这就是为什么原始类型是&#34;坏&#34;,因为原始类型与不使用泛型之间基本没有区别。

试试这个:

SomeClass<String> pam = new SomeClass<String>();

((SomeClass)pam).set(new Integer(0));

System.out.println(((SomeClass)pam).get()); // prints 0
System.out.println(pam.get()); // ClassCastException

所以要明确的是,当你这样做时:

SomeClass<String> instance1 = new SomeClass<>();
SomeClass instance2 = instance1;

没有类型通过&#34;通过&#34;。 instance2不是SomeClass<String>

执行此操作时:

SomeClass instance1 = new SomeClass();
SomeClass<String> instance2 = instance1;

您收到警告,因为它不安全。我无法保证instance1的值是一个字符串,但如果您调用get instance2,它将被转换为一个字符串。

给出以下代码段:

SomeClass<String> instance1 = new SomeClass<String>();
SomeClass instance2 = instance1;

System.out.println(instance1.get());
System.out.println(instance2.get());

print语句编译为以下字节码:

getstatic PrintStream System.out
aload_1 instance1
invokevirtual Object SomeClass.get()           // instance1.get() returns Object
checkcast String                               // which is casted to String
invokevirtual void PrintStream.println(String) // call println for String
getstatic PrintStream System.out
aload_2 instance2
invokevirtual Object SomeClass.get()           // instance2.get() returns Object
invokevirtual void PrintStream.println(Object) // call println for Object

正如你所看到的,除了演员之外没有区别。

相关问题