首先看一个例子:
public class JavaFanXing {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("aaaaaa");
list.add("sssss");
list.add(11);
for(int i=0;i<list.size();i++){
String str = (String) list.get(i);
System.out.println(str);
}
}
}
老生常谈的例子:我们定义一个list容器,其中可以放各种类型的数据,如上述例子:我们先存放了两个字符类型的,又放了一个整型的,编译通过但是在运行时会报java.lang.ClassCastException的错误,因为此时list默认是Object类型的,但是当我们向外取数需要将其转化为字符型时就出错了。此时我们需要一种方法,只要编译通过,就可以运行,所以此时就需要泛型了。
泛型就是在编写代码时定义一些可变的部分,这些部分在使用前必须做出定义,就类似与我们定义方法时要定义形参,而在使用这个方法时我们需要传入实参,然后才能使用。而泛型传入的参数并不是一个对象或者变量,而是一个类,java的泛型的参数只代表类。
ArrayList<T> arrayString=new ArrayList<T>();
我们用泛型来实现一下上边的例子:
public class JavaFanXing {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("aaaaaa");
list.add("sssss");
//list.add(11);此时这里传入非String类型的数据就会报错
for(int i=0;i<list.size();i++){
String str = (String) list.get(i);
System.out.println(str);
}
}
}
都说java的泛型是伪泛型,那么java的泛型在内存中到底是如何存在的呢?我们可以通过下边案例窥探一二
public class Test{
public static void main(String[] args) {
ArrayList<String> arrayString=new ArrayList<String>();
ArrayList<Integer> arrayInteger=new ArrayList<Integer>();
System.out.println(arrayString.getClass()==arrayInteger.getClass()); //true
}
}
最后输出结果是true,证明泛型中传入的参数随不同,却并没有开辟不同的内存空间,反而还是同一个东西。
这是因为泛型只在编译阶段有效,即便你分别传入两个不同类型泛型实参,但其在内存中仍只有一个在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。
简单来说:泛型就是给容器指定一个可以存储的类,比如说原先有一口缸,缸里边可以放水,也可以放面粉。但是放了水的缸也可以放面粉,但是这样就太乱了。所以现在指定,这是个水缸,他只能放水,不能放面粉否则就报错。 当然我们也可以把它指定为一个面粉缸,那么现在就只能放面粉不能向里边放水。但是不管放水还是放面粉,这个缸还是这个缸,就相当于不管你往这个容器里边传什么参数,在java的内存中这个容器的位置是不变的。
参考:http://blog.csdn.net/sunxianghuang/article/details/51982979