一、限制泛型可用类型
① 在定义泛型类型时,默认在实例化泛型类的时候可以使用任何类型,但是如果想要限制使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个类;
② 当没有指定泛型继承的类型或接口时,默认使用extends Object,所以默认情况下任何类型都可以作为参数传入;
继承抽象类
1 public class GenericDemo3{ 2 public static void main(String []args){ 3 GenericClass<Dog> dogClass=new GenericClass<Dog>(); 4 dogClass.setObj(new Dog()); 5 dogClass.getObj().eat(); 6 7 8 GenericClass<Cat> catClass=new GenericClass<Cat>(); 9 catClass.setObj(new Cat()); 10 catClass.getObj().eat(); 11 } 12 } 13 14 //泛型类所接受的参数做了限制,只能接收Animal类型或者Animal类的子类 15 class GenericClass<T extends Animal>{ 16 private T obj; 17 public void setObj(T obj){ 18 this.obj=obj; 19 } 20 public T getObj(){ 21 return obj; 22 } 23 } 24 25 abstract class Animal{ 26 public abstract void eat(); 27 } 28 29 class Dog extends Animal{ 30 public void eat(){ 31 System.out.println("啃骨头"); 32 } 33 } 34 class Cat extends Animal{ 35 public void eat(){ 36 System.out.println("吃鱼肉"); 37 } 38 }
继承接口
1 public class GenericDemo3{ 2 public static void main(String []args){ 3 GenericClass<Dog> dogClass=new GenericClass<Dog>(); 4 dogClass.setObj(new Dog()); 5 dogClass.getObj().eat2(); 6 7 8 GenericClass<Cat> catClass=new GenericClass<Cat>(); 9 catClass.setObj(new Cat()); 10 catClass.getObj().eat2(); 11 } 12 } 13 14 //泛型类所接受的参数做了限制,只能接收Animal类型或者Animal类的子类 15 class GenericClass<T extends Animal2>{ 16 private T obj; 17 public void setObj(T obj){ 18 this.obj=obj; 19 } 20 public T getObj(){ 21 return obj; 22 } 23 } 24 25 interface Animal2{ 26 public abstract void eat2(); 27 } 28 29 class Dog implements Animal2{ 30 public void eat2(){ 31 System.out.println("啃骨头2"); 32 } 33 } 34 class Cat implements Animal2{ 35 public void eat2(){ 36 System.out.println("吃鱼肉2"); 37 } 38 }
二、类型通配符声明
① 同一泛型类,如果实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值;
Generic<Boolean> f1=new Generic<Boolean>();
Generic<Integer> f2=new Generic<Integer>();
f1=f2;//发生编译错误
Generic<Object> f=f1;//f1和f类型并不兼容,发生编译错误
f=f2;//f2和f类型同样不兼容,也会发生编译错误
② 泛型类实例之间的不兼容性会带来使用的不便。我们可以使用泛型通配符(?)声明泛型类的变量就可以解决这个问题;
③ 泛型通配符的方式
“?”代表任意一个类型;
Generic<Boolean> f1=new Generic<Boolean>();
Generic<?> f=f1;
和限制泛型的上限相似,同样可以使用extends关键字限定通配符匹配类型的上限;
Generic<Dog> f1=new Generic<Dog>();
Generic<? extends Animal> f=f1;
还可以使用super关键字将通配符类型限定为某个类型及其父类型;
Generic<Animal> f1=new Generic<Animal>();
Generic<? super Dog> f=f1;
1 public class GenericDemo4{ 2 public static void main(String []args){ 3 GenericClass<Dog> dogClass=new GenericClass<Dog>(); 4 dogClass.setObj(new Dog()); 5 dogClass.getObj().eat(); 6 7 GenericClass<Cat> catClass=new GenericClass<Cat>(); 8 catClass.setObj(new Cat()); 9 catClass.getObj().eat(); 10 11 GenericClass<String> StringClass=new GenericClass<String>(); 12 13 //dogClass=catClass;//编译出错 14 15 //无限定通配符的使用 16 GenericClass<?> gClass=null; 17 gClass=dogClass; 18 ((Dog)gClass.getObj()).eat();//因父类为object类型,所以要强制转换 19 20 gClass=StringClass; 21 22 //上边界限定通配符 23 GenericClass<? extends Animal> subclass=null; 24 subclass=dogClass; //Animal a=dog; 25 subclass.getObj().eat(); 26 27 //下边界限定通配符 28 GenericClass<? super Dog> sclass=null; 29 GenericClass<Animal> cClass=new GenericClass<Animal>(); 30 //sclass=catClass; //编译错误,类型不兼容 31 sclass=cClass;//可以通过编译 32 } 33 } 34 35 36 class GenericClass<T>{ 37 private T obj; 38 public void setObj(T obj){ 39 this.obj=obj; 40 } 41 public T getObj(){ 42 return obj; 43 } 44 } 45 46 interface Animal{ 47 public abstract void eat(); 48 } 49 50 class Dog implements Animal{ 51 public void eat(){ 52 System.out.println("啃骨头"); 53 } 54 } 55 class Cat implements Animal{ 56 public void eat(){ 57 System.out.println("吃鱼肉"); 58 } 59 }
三、泛型方法
① 不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。其定义格式为:
访问修饰符<泛型列表> 返回类型 方法名(参数列表){
实现代码
}
② 在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明;
③ 类中其它方法不能使用当前方法声明的泛型;
注:是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前;
④ 什么时候使用 泛型方法,而不是泛型类?
添加类型约束只作用于一个方法的多个参数之间,而不涉及到类中的其它方法;
施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型参数;
1 public class GenericDemo5{ 2 public static void main(String []args){ 3 GenericClass2 gen=new GenericClass2(); 4 gen.println("abc"); 5 gen.println(true); 6 gen.println(10); 7 gen.println(10.5); 8 gen.println(new Dog()); 9 gen.println(new Cat()); 10 GenericClass2.print("哈哈"); 11 } 12 } 13 14 class GenericClass2{ 15 //泛型方法 16 public <T> void println(T content){ 17 System.out.println(content); 18 } 19 //泛型方法的重载 20 public <T extends Animal> void println(T animal){ 21 animal.eat(); 22 } 23 24 public static <T> void print(T content){ 25 System.out.println(content); 26 } 27 } 28 29 interface Animal{ 30 public abstract void eat(); 31 } 32 33 class Dog implements Animal{ 34 public void eat(){ 35 System.out.println("啃骨头"); 36 } 37 } 38 class Cat implements Animal{ 39 public void eat(){ 40 System.out.println("吃鱼肉"); 41 } 42 }