如果将参数化类型对象分配给原始类型对象,据我所知,原始类型对象采用参数化类型。这对我来说很有意义。但为什么它不能相反呢?我认为在将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正在创建一个指针而不是一个新对象,并且一个指针不能改变它所指向的对象的行为?
答案 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
正如你所看到的,除了演员之外没有区别。