泛型是jdk1.5之后java出现的另一新的特性。虽然是比较新的东西,但是泛型的出现却是必然,比如若想要在函数参数中,以不同的类型,进行传入。当然可以使用泛化来实现参数多个类型的接受,但是,若在编译期间未正确的转型编译器也并不会显式的提醒这一错误。而使用泛型则很好的解决了这一问题。
简单的泛型示例:
public class Animal <T>{
T item;
public Animal(T item){
this.item = item;
}
public T getItem(){
return item;
}
public static void main(String[] args) {
Animal <String> animal1 = new Animal<String>("animal");
System.out.println("animal1:"+animal1.getItem());
Animal <Integer> animal2 = new Animal<Integer>(20);
System.out.println("animal2:"+animal2.getItem());
Animal<Animal> animal3 = new Animal<Animal>(animal1);
System.out.println("animal3:"+animal3.getItem());
}
}
output:
animal1:animal
animal2:20
com.test.Animal@7629b854
在上述示例中我们不难发现,泛型是如此灵活,使用泛型的参数,使得我们单个功能的程序复用性更强,同时泛型方法在使用时,规定传入参数,这样就避免了我们在应用泛化,进行向下转型时出现的类型转换错误。
而泛型的出现不仅仅可以实现,参数类型的的可变,同时还可以应用泛型的特点来实现一个方法中返回多个对象。既元组。
public class Twotuple<A,B> {
public final A item1;
public final B item2;
Twotuple(A a,B b){
item1=a;
item2= b;
}
public String toString(){
return "[item1:"+item1+", item2:"+item2+"]";
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new Twotuple< Integer,String>(222,"hello").toString());
}
}
output:
[item1:222, item2:hello]
我们通过创建一个对象,来持有多个任意类型的对象引用。而final 关键字则保证了我们在第一次赋值后,就无法再次改变一个元组中所持有的对象引用,而这样做的好处既使得代码更加简洁。
我们同样也可以使用泛型来实现泛型方法如下:
public class Demo {
public static <T> void method(T t){
System.out.println("[class type:"+t.getClass()+",parameter name:"+t.getClass().getName()+"]");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
method(1);
method("hello");
method(new Demo());
}
}
output:
[class type:class java.lang.Integer,parameter name:java.lang.Integer]
[class type:class java.lang.String,parameter name:java.lang.String]
[class type:class com.test.Demo,parameter name:com.test.Demo]
泛型的出现确实解决了java中在jdk1.5之前的一些问题。但因为java中的泛型是通过擦出实现,所以在使用泛型的过程中,实际上编译器会将具体类型擦出,所以既会造成这一情况的发生:
public class Demo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1 == c2);
}
}
output:true
而相同的情况,在c++的模板中,却并不会发生。但擦出作为一种比较折中的实现泛型的方式,还是可以通过限定边界的方式来实现类型的限制
<T extends classtype>
泛型确实可以解决一些泛化所无法完成的问题,但是由于实现机制为擦除导致泛型在编译时时如上述情况将类型都转化为最基本类型。但泛型的出现,还是很大程度上,解决了一些泛化中出现的问题。