诊断Java代码: 轻松掌握Java泛型类型,第2部分 - 编程入门网
) { return member; }
public static void main(String[] args) {
C<String> c = new C<String>("test");
System.out.println(c.getMember().toString());
new C<Integer>(new Integer(1));
System.out.println(c.getMember().toString());
}
}
请注意,每次分配类 C 的实例时,都要重新设置静态字段 member 。而且,它被设置成的对象类型取决于 C 的实例的类型!在所提供的 main 方法中,第一个实例 c 是 C<String> 类型。而第二个是 C<Integer> 类型。每当从 c 访问 member 这一共享静态字段时,总是假定 member 的类型是 String 。但是,在分配了类型为 C<Integer> 的第二个实例之后, member 的类型是 Integer 。 运行 C 的 main 方法的结果可能会让您吃惊 ― 它将发出一个 ClassCastException !源代码根本没有包含任何数据类型转换,怎么会这样呢?事实证明编译器确实在编译阶段将数据类型转换插入到代码中,这样做是为了解决类型擦除会降低某些表达式的类型的精度这一事实。这些数据类型转换 被期望能够成功,但在本例中却没有成功。 应该认为 JSR-14 1.0 和 1.2 的这一特殊“功能”是个错误。它破坏了类型系统的健全性,或者可以说,它破坏了类型系统应该和程序员达成的“基本契约”。象对静态方法和类所做的那样,只要防止程序员在静态字段中引用泛型类型,情况就会好很多。 请注意允许这种有潜在“爆炸性”的代码存在所带来的问题并不是程序员 有意在自己的代码中覆盖类型系统。问题是程序员可能会无意中编写这样的代码(比如,由于“复制和粘贴”操作,错误地在字段声明中包括静态修饰符)。 类型检查器应该能帮助程序员从这些类型的错误中恢复,但对于静态字段而言,类型系统实际上会使程序员更迷惑。当未使用数据类型转换的代码中显示的唯一错误就是 ClassCastException 时,我们应如何诊断这样的错误?对于不清楚 Tiger 中泛型类型所用的实现方案而又恰好假定类型系统合理运行的程序员而言,情况更糟。因为在这样的情况下,类型系统不是合理地运行。 幸运的是,JSR-14 的最新版本(1.3)宣布在静态字段中使用类型参数是不合法的。因此,我们有理由期待在 Tiger 的静态字段中使用类型参数也是不合法的。 泛型类型参数和基本类型 和我们刚才讨论的不同,这一限制没有同样的潜在缺陷,但它会使您的代码非常冗长。例如,在 java.util.Hashtable 的泛型版本中,有两种类型参数:用于 Key 类型的和用于 Value 类型的。因此,如果我们想要一个将 String 映射到 String 的 Hashtable ,我们可以用表达式 new Hashtable<String, String>() 指定新的实例。但是,如果我们想要一个将 String 映射到 int 的 Hashtable ,我们只能创建 Hashtable<String, Integer> 的实例,并将所有的 int 值包装在 Integer 中。 同样,Tiger 在这方面当然也是由所用的实现方案得到的。既然类型参数被擦除为它们的界限,而界限不能是基本类型,所以一旦类型被擦除,则对基本类型的实例化会完全没有意义。 数据类型转换或 instanceof 操作中的“外露”参数 回想一下,对于“外露”类型参数,我们是指在词汇上单独出现的类型参数,而不是更大类型的语法子组件。例如, C<T> 不是“外露”类型参数,但(在 C 主体中) T 是。 诊断Java代码: 轻松掌握Java泛型类型,第2部分(3)时间:2011-02-11 IBM Eric E. Allen如果在代码中对“外露”类型参数进行数据类型转换或 instanceof 操作,则编译器将发出名为“unchecked”的警告。例如,以下代 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |