【发布时间】:2012-11-30 00:35:17
【问题描述】:
必须翻译泛型类型或方法(任何语言,而不仅仅是 Java)的编译器原则上有两种选择:
代码专业化。编译器为 泛型类型或方法的每个实例化。例如, 编译器将生成整数列表和其他代码, 字符串列表、日期列表、日期列表的不同代码 缓冲区等。
代码共享。编译器只为一种表示生成代码 泛型类型或方法,并映射 泛型类型或方法的唯一表示,执行类型 在需要时检查和类型转换。
Java 使用代码共享方法。我相信 C# 遵循 code specialization 方法,所以根据我使用 C# 的方式,下面的所有代码都是合乎逻辑的。
假设这个Java代码sn-p:
public class Test {
public static void main(String[] args) {
Test t = new Test();
String[] newArray = t.toArray(new String[4]);
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
//5 as static size for the sample...
return (T[]) Arrays.copyOf(a, 5, a.getClass());
}
}
代码共享方式类型擦除发生后会导致此代码:
public class Test {
public static void main(String[] args) {
Test t = new Test();
//Notice the cast added by the compiler here
String[] newArray = (String[])t.toArray(new String[4]);
}
@SuppressWarnings("unchecked")
public Object[] toArray(Object[] a) {
//5 as static size for the sample...
return Arrays.copyOf(a, 5, a.getClass());
}
}
所以我的问题是:
需要精确这个初始演员阵容吗? :
(T[]) Arrays.copyOf(a, 5, a.getClass());
而不是简单地做(在类型擦除之前,在编码时):
Arrays.copyOf(a, 5, a.getClass());
编译器真的需要这种转换吗?
好的,Arrays.copyOf 返回Object[] 并且在没有明确向下转换的情况下不能被更具体的类型直接引用。
但是编译器不能在这种情况下做出努力,因为它处理的是泛型类型(返回类型!)?
确实,编译器对方法的调用行应用显式强制转换还不够? :
(String[])t.toArray(new String[4]);
已更新------------------------------- --------------------------
感谢@ruakh 的回答。
这里有一个示例,它证明了即使只是在编译时出现的显式转换也是相关的:
public static void main(String[] args) {
Test t = new Test();
String[] newArray = t.toArray(new String[4]);
}
public <T> T[] toArray(T[] a) {
return (T[]) Arrays.copyOf(a, 5, Object[].class);
}
投射到T[] 是向用户发出警告的唯一方法,表明投射可能不相关。事实上,这里我们最终将Object[] 向下转换为String[],这导致在运行时ClassCastException。
所以,说到“编译器对方法的调用行应用显式转换还不够”,答案是:
开发人员不掌握这种转换,因为它是在编译步骤自动创建的,因此此运行时功能不会警告用户在启动编译之前深入检查其代码的安全性。
简而言之,这个演员阵容值得出席。
【问题讨论】:
-
上一个示例中的
t是什么? -
t只是Test示例类的实例。它只是上面整个代码的摘录。
标签: c# java generics compiler-construction casting