java泛型作用主要分为泛型类泛型接口,泛型方法。
看一个例子:
package collection;
public class Gen<T> {
private T ob;
public Gen(T ob) {
this.ob = ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void showType() {
System.out.println("T的类型是:" + ob.getClass().getName());
}
}
建一个测试类
package collection;
public class GenTest {
public static void main(String[] args) {
Gen<Integer> intob=new Gen<Integer>(88);
intob.showType();
Gen<String> strob=new Gen<String>("ccccccccc");
strob.showType();
System.out.println(intob.getClass());
System.out.println(strob.getClass());
System.out.println(intob.getClass()==strob.getClass());
}
}
测试结果
T的类型是:java.lang.String
class collection.Gen
class collection.Gen
true
可以看到什么是泛型,即参数化类型,如果不用泛型的话就的直接进行类型转换。在使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,即还是原来的最基本的类型(本实例中为Gen),当然,在逻辑上我们可以理解成多个不同的泛型类型。
究其原因,在于Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。
对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。
参见的泛型参数主要是T、E、K、V
T一般是类中,E一般用在接口中,K、V主要用在Map里面
还有类型通配符?
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(42));
List<?> lu = li;
System.out.println(lu.get(0));
为什么该代码能工作呢?对于 lu,编译器一点都不知道 List 的类型参数的值。但是编译器比较聪明,它可以做一些类型推理。在本例中,它推断未知的类型参数必须扩展 Object。
另一方面
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(42));
List<?> lu = li;
lu.add(new Integer(43)); // error
在本例中,对于 lu,编译器不能对 List 的类型参数作出足够严密的推理,以确定将 Integer 传递给 List.add() 是类型安全的。所以编译器将不允许您这么做。
看一个例子
List myIntList=new LinkedList(); //1
myIntList.add(newInteger(0)); //2
Integer x=(Integer)myIntList.iterator().next(); //3
这里需要进行类型转换,下面这个使用泛型,就不需要转换
List<Integer> myIntList=newLinkedList<Integer>(); //1’
myIntList.add(newInteger(0)); //2’
Integerx=myIntList.iterator().next(); //3’
泛型和子类型
List<Apple> apples = new ArrayList<Apple>(); //1
List<Fruit> fruits = apples; //2
在这里,Apple是子类,Fruit是父类u,但第二行代码是错误的。
为什么一箱苹果就不是一箱水果了呢?可以这样考虑,我们假定第2行代码没有问题,那么我们可以使用语句fruits.add(new Strawberry())(Strawberry为Fruit的子类)在fruits中加入草莓了,但是这样的话,一个List中装入了各种不同类型的子类水果,这显然是不可以的,因为我们在取出List中的水果对象时,就分不清楚到底该转型为苹果还是草莓了。