浅析Java泛型
表面上看起来,无论语法还是应用的环境(比如容器类),泛型类型(或者泛型)都类似于 C++ 中的模板。但是这种相似性仅限于表面,Java 语言中的泛型基本上完全在编译器中实现,由编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码。这种实现技术称为擦除(erasure)(编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除),这项技术有一些奇怪,并且有时会带来一些令人迷惑的后果。虽然范型是 Java 类走向类型安全的一大步,但是在学习使用泛型的过程中几乎肯定会遇到头痛(有时候让人无法忍受)的问题。
注意:本文假设您对 JDK 5.0 中的范型有基本的了解。
泛型不是协变的
虽然将集合看作是数组的抽象会有所帮助,但是数组还有一些集合不具备的特殊性质。Java 语言中的数组是协变的(covariant),也就是说,如果 Integer 扩展了 Number(事实也是如此),那么不仅 Integer 是 Number,而且 Integer[] 也是 Number[],在要求 Number[] 的地方完全可以传递或者赋予 Integer[]。(更正式地说,如果 Number 是 Integer 的超类型,那么 Number[] 也是 Integer[] 的超类型)。您也许认为这一原理同样适用于泛型类型 —— List<Number> 是 List<Integer> 的超类型,那么可以在需要 List<Number> 的地方传递 List<Integer>。不幸的是,情况并非如此。
不允许这样做有一个很充分的理由:这样做将破坏要提供的类型安全泛型。如果能够将 List<Integer> 赋给 List<Number>。那么下面的代码就允许将非 Integer 的内容放入 List<Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
因为 ln 是 List<Number>,所以向其添加 Float 似乎是完全合法的。但是如果 ln 是 li 的别名,那么这就破坏了蕴含在 li 定义中的类型安全承诺 —— 它是一个整数列表,这就是泛型类型不能协变的原因。
其他的协变问题
数组能够协变而泛型不能协变的另一个后果是,不能实例化泛型类型的数组(new List<String>[3] 是不合法的),除非类型参数是一个未绑定的通配符(new List<?>[3] 是合法的)。让我们看看如果允许声明泛型类型数组会造成什么后果:
List<String>[] lsa = new List<String>[10]; // illegal
Object[] oa = lsa; //
相关文档:
1.[http://www.javaalmanac.com] – Java开发者年鉴一书的在线版本. 要想快速查到某种Java技巧的用法及示例代码, 这是一个不错的去处.
2.[http://www.onjava.com] – O’Reilly的Java网站. 每周都有新文章.
3.[http://java.sun.com] – 官方的Java开发者网站 – 每周都有新文章发表.
4.[http:/ ......
- 加入菜鸟学习网,获得珍藏资源
Java代码 数据挖掘中决策树C4.5预测算法实现(半成品,还要写规则后剪枝及对非离散数据信息增益计算) Java代码 package org.struct.decisiontree; import java.util.ArrayList; import java.util.Arrays; ......
1、 认识Thread和Runnable
Java中实现多线程有两种途径:继承Thread类或者实现Runnable接口。Runnable是接口,建议用接口的方式生成线程,因为接口可以实现多继承,况且Runnable只有一个run方法,很适合继承。在使用Thread的时候只需继承Thread,并且new一个实例出来,调用start()方法即可以启动一个线程。
Thread Test = ......
以前为了过滤Java的ISO-8859-1字符,总是使用如下代码来处理。
view plaincopy to clipboardprint?
String strUserame = (String)reuqest.getParameter("username");
strUsername = new String(strUserame.getBytes("ISO-8859-1"),"UTF-8");
String strUserame ......