Java高级-Java泛型简介
泛型简介
泛型是JDK1.5引入的新特性,也是最重要的一个特性。
泛型可以在编译的时候检查类型安全,并且所有的强制转换都自动和隐式的。
泛型的原理就是“类型的参数化”,即把类型看做参数。也就是说要把所要操作的数据类型看做参数,就像方法的形式参数是运行时传递的值的占位符一样。
简单的说,类型变量扮演的角色就如同一个参数,它提供给编译器类型检查的信息。
泛型可以提高代码的扩展性和重用性,类型抽象化从而实现更为灵活的复用。
使用注意
1、泛型的类型参数可以是常规的引用数据类型,也可以是泛型类
2、泛型类可以同时设置多个类型参数
3、泛型类可以继承泛型类
4、泛型类可以实现泛型接口
限制泛型可用类型
在定义泛型类别时,默认在实例化泛型类的时候可以使用任何引用类型,但是如果想要限制使用泛型类型时只能使用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须继承某个类或者实现某个接口。
当没有指定泛型继承的类型或接口时,默认使用extends Object。
类型通配声明
同一泛型类,如果实例化时给的实际类型不同,则这些实例类型是不兼容的,不能相互赋值。
可以使用泛型通配符(?)声明泛型类型变量,可以解决兼容问题。
泛型通配符使用:
GenClass<Integer> f1=new GenClass<Integer>();
GenClass<?> f2=f1;
泛型通配符限定的使用:
限定类型上限:
GenClass<Dog> f1=new GenClass<Dog>();
GenClass<? extends Animal> f2=f1;//限定类型为Animal及其子类
限定类型下限:
GenClass<Animal> f1=new GenClass<Animal>();
GenClass<? super Dog> f2=f1;//限定类型为Dog及其父类(或接口)
泛型方法
泛型方法定义示例:
public <T> void println(T content){} //默认extends Object
public <T extends Animal> void println(T animal){}
泛型方法调用示例:obj.println("str");//T类型可以被自动推测
demo:
public class GenericClassDemo{ public static void main(String[] args){ testDemo1(); } public static void testDemo1(){ GenClass<String> gen1=new GenClass<String>("stringTest"); System.out.println(gen1.getData()); GenClass<Integer> gen2=new GenClass<Integer>(100); System.out.println(gen2.getData()); //System.out.println((String)gen2.getData());//强转,编译不通过 GenClass<Student> gen3=new GenClass<Student>(new Student("张三")); GenClass<GenClass<Student>> gen4=new GenClass<GenClass<Student>>(gen3); System.out.println(gen4.getData().getData()); System.out.println("————————————————————"); GenClass2<String,Integer> gen5=new GenClass2<String,Integer>("zhang",10); System.out.println("多参数泛型对象 data1:"+gen5.getData1()+" data2:"+gen5.getData2()); System.out.println(); SubClass<Integer,String> gen6=new SubClass<Integer,String>(1000,"java"); System.out.println("继承泛型类、实现泛型接口的泛型类对象 data1:"+gen6.getData1()+" data2:"+gen6.getData2()); System.out.println("————————————————————"); GenClass3<Dog> gen7=new GenClass3<Dog>(new Dog()); gen7.getObj().eat(); GenClass3<Cat> gen8=new GenClass3<Cat>(new Cat()); gen8.getObj().eat(); //下行编译错误: 类型参数String不在类型变量T的范围内 //GenClass3<String> gen9=new GenClass3<String>("test"); System.out.println("————————————————————"); //无限定通配符 //GenClass3<?> gClass //任意类型 //限定gClass只能是Aminal及其子类对象,如果是其他的就会报错 GenClass3<? extends Animal> gClass=null;//声明一个通配引用变量 System.out.println("? extends Animal通配引用变量使用:"); gClass = gen7; gClass.getObj().eat(); gClass = gen8; gClass.getObj().eat(); System.out.println("? super Dog通配引用变量使用:"); GenClass3<? super Dog> sClass=null;//声明一个通配引用变量 GenClass3<Animal> aClass=new GenClass3<Animal>(); //sClass=gen8;//Cat泛型对象,报错: 不兼容的类型 sClass=aClass;//正确,Dog的父类 sClass=gen7;//Dog泛型对象,正确 sClass.getObj().eat(); } } //定义泛型类 class GenClass<T>{ private T data; public GenClass(){ } public GenClass(T data){ this.data=data; } public void setData(T data){ this.data=data; } public T getData(){ return data; } } class Student{ private String name; public Student(String name){ this.name=name; } public String toString(){ return "学生:"+name; } } //多个类型参数的泛型类,用,号分开类型参数 class GenClass2<T1,T2>{ private T1 data1; private T2 data2; public GenClass2(){ } public GenClass2(T1 data1,T2 data2){ this.data1=data1; this.data2=data2; } public void setData(T1 data1,T2 data2){ this.data1=data1; this.data2=data2; } public T1 getData1(){ return data1; } public T2 getData2(){ return data2; } } //泛型类继承泛型类demo //泛型父类 class SuperClass<T1>{ private T1 data1; public SuperClass(T1 data1){ this.data1=data1; } public T1 getData1(){ return data1; } } //泛型接口 interface IInfo<T2>{ public abstract T2 getData2(); } //泛型子类,实现泛型接口 class SubClass<T1,T2> extends SuperClass<T1> implements IInfo<T2>{ private T2 data2; public SubClass(T1 data1,T2 data2){ super(data1); this.data2=data2; } //可以重写父类方法 public T1 getData1(){ return super.getData1(); } //实现接口 public T2 getData2(){ return data2; } } //限制泛型类的类型变量类型 //由于T继承自Animal,那么GenClass3内部知道obj对象是Animal或其子类的实例,可以调用其相应的方法或成员属性 class GenClass3<T extends Animal>{/* 如果是限定接口也是用 extends 接口名 */ private T obj; public GenClass3(){ } public GenClass3(T obj){ this.obj=obj; } public void setObj(T obj){ this.obj=obj; } public T getObj(){ return obj; } } interface IAnimal{ public abstract void eat(); } abstract class Animal{ public abstract void eat(); } class Dog extends Animal{ public void eat(){ System.out.println("dog 啃骨头"); } } class Cat extends Animal{ public void eat(){ System.out.println("cat 吃鱼"); } }
效果: