首先让我们来看一个小例子
public class GenericTest { public static void main(String[] args) { List list = new ArrayList(); list.add("qq"); list.add("pp"); list.add(100); for (int i = 0; i < list.size(); i++) { String name = (String)list.get(i); System.out.println("name: "+ name); } }看看会报错吗?
会的,输出前两个没问题,但是输出第三个100 时候就报错了...
上面的List集合,既可以添加String类型又可以添加Integer类型,是完全允许的 因为此时的List默认的类型Object类型。 然而在之后的循环中,可能会忘记list里面还有Integer类型的值,很容易出现 java.lang.ClassCastException这种异常,因此,导致此类错误编码过程中不易发现。。 上面的代码有两个问题: 1.当我们将对象放入集合以后,集合不会记住此对象的类型,当再次从集合中取出此对象时, 对象的编译类型就变成了Object类型,运行时候任然为其本身 2.在list.get(i) 取出集合元素的时候,需要人为的强制类型转换到具体的目标类型, 且很容易出现"java.lang.ClassCastException"异常 那么有没有什么办法可以使集合能够记住集合内元素各类型, 且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常呢? 答案就是使用泛型。 什么是泛型? 泛型,即"参数化类型".一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。 那么参数化类型怎么理解呢? 顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数。 此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。 看着好像有点复杂,首先我们看下上面那个例子采用泛型的写法。
再来看一个小例子..
public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("qq"); list.add("pp"); // list.add(100); for (int i = 0; i < list.size(); i++) { String name = (String)list.get(i); System.out.println("name: "+ name); } }
采用泛型写法后,再想往list集合中添加一个Integer类型的对象的时候就会出现编译错误。 通过List<String> 直接限定了list集合中 只能含有String类型的元素,从而在输出的时候无需转换。 因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。
那我们再来看另一个例子..
一个简单的定义泛型的例子 */ public class GenericTest2 { public static void main(String[] args) { Box<String> name = new Box<String>("corn"); System.out.println("name: "+ name.getData()); } } class Box<T> { private T data; public Box() { } public Box(T data) { this.data = data; } public T getData() { return data; } }
/* 在泛型接口、泛型类和泛型方法的定义过程中, 我们常见的如T、E、K、V等形式的参数常用于表示泛型形参, 由于接收来自外部使用时候传入的类型实参。 那么对于不同传入的类型实参,生成的相应对象实例的类型是不是一样的呢? */ public static void main(String[] args) { Box<String> name = new Box<String>("corn"); Box<Integer> age = new Box<Integer>(71); System.out.println("name: "+name.getClass());//com.generic.test.Box System.out.println("age: "+age.getClass()); //com.generic.test.Box System.out.println(name.getClass() == age.getClass());//true } /* 由此,我们发现,在使用泛型类时,虽然传入了不同的泛型实参, 但并没有真正意义上生成不同的类型, 传入不同泛型实参的泛型类在内存上只有一个, 即还是原来的最基本的类型(本实例中为Box),当然, 在逻辑上我们可以理解成多个不同的泛型类型。 */
挑取了一些贴出来了,原文在此..
http://www.imooc.com/article/1935