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

J S*_*J S 2 java generics types

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

谢谢你的帮助!

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

SomeClass<String> instance1 = new SomeClass<>();
SomeClass instance2 = instance1;
Run Code Online (Sandbox Code Playgroud)

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

SomeClass instance1 = new SomeClass();
SomeClass<String> instance2 = instance1;
Run Code Online (Sandbox Code Playgroud)

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

Rad*_*def 5

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

考虑以下内容:

class SomeClass<T> {
    T value;

    T get() {
        return value;
    }

    void set(T val) {
        value = val;
    }
}
Run Code Online (Sandbox Code Playgroud)

当你声明一个新的SomeClass时,它看起来像是这样的:

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

    String get() {
        return value;
    }

    void set(String val) {
        value = val;
    }
}
Run Code Online (Sandbox Code Playgroud)

但这不是实际发生的事情.实际发生的是SomeClass总是这样:

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

    Object get() {
        return value;
    }

    void set(Object val) {
        value = val;
    }
}
Run Code Online (Sandbox Code Playgroud)

当你有一个SomeClass<String>,无论何时你说SomeClass<String>,编译器都会从Object转换为String.在运行时,原始时间和参数化类型之间没有行为差异,只有是否存在强制转换.这就是原始类型"糟糕"的原因,因为原始类型与不使用泛型之间基本没有区别.

试试这个:

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
Run Code Online (Sandbox Code Playgroud)

所以要清楚,当你这样做时:

SomeClass<String> instance1 = new SomeClass<>();
SomeClass instance2 = instance1;
Run Code Online (Sandbox Code Playgroud)

没有类型被"通过".String someString = someClass.get();不是instance2.

当你这样做:

SomeClass instance1 = new SomeClass();
SomeClass<String> instance2 = instance1;
Run Code Online (Sandbox Code Playgroud)

你得到一个警告,因为它不安全.不能保证SomeClass<String>值是一个字符串,但如果你打电话,它将被转换成一个字符串instance1.

给出以下代码段:

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

System.out.println(instance1.get());
System.out.println(instance2.get());
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如你所见,除了演员之外没有区别.