六、泛型——2-深入泛型
2-深入泛型
泛型,就是允许在定义类、接口、方法时使用类型形参,这个形参将在声明变量、创建对象、调用方法时动态指定。
1.定义泛型接口、类
(1)包含泛型声明的类型可以在定义变量、创建对象时传入一个类型实参,从而可以在使用时动态的生成无数个逻辑上的子类,但这种子类在物理上不存在;
(2)可以在任何的类、接口增加泛型声明;
(3)当创建带泛型声明的类,在为该类定义构造器时,构造器还是原来的类名,不需要再添加泛型声明;
(4)为接口添加泛型声明
import java.util.List; //在这里添加泛型声明<T>,接口中可以使用T作为一个类型 public interface MyInterface<T> { public void add(T t); //把T当做类型使用 public List<T> getList(); //返回值类型为元素为T的List集合 public T getT(); //直接返回类型T的对象 }
(5)为类添加泛型声明
public class MyClass<T> { public T t; //把类型T当做一个实例变量 //构造方法 //构造方法不添加泛型声明 public MyClass(){ } }
(6)简单使用
//使用泛型声明 public class Apple<T> { //使用T类型形参定义实例变量 private T info; public Apple(){ } //使用T类型定义构造器 public Apple(T info){ this.info = info; } //setter、getter方法 public T getInfo() { return info; } public void setInfo(T info) { this.info = info; } public static void main(String[] args) { //传给T形参的是String,所以构造器参数只能是String Apple<String> apple = new Apple<>("苹果"); System.out.println(apple.getInfo()); //传给T形参的是Double,所以构造器参数只能是Double或者double Apple<Double> apple2 = new Apple<>(5.23); System.out.println(apple2.getInfo()); } }
2.从泛型类派生子类
当创建了带泛型的接口、父类之后,就可以为这些接口、父类创建实现类或者派生出子类,但是使用这些接口、父类时,不能再携带泛型:
如有:public class People<T>{...}
错误:public class Student extends People<T>{...}
正确1:public class Student extends People<String>{...}
//传入具体类型 所有在父类中、或接口中的T都成为了String类型
正确2:public class Student extends People{...}
//不携带泛型参数 所有在父类中、接口中的T都成为了Object类型
3.不存在泛型类
(1)两个类型相同,泛型参数不同的对象相比较:
import java.util.ArrayList; import java.util.List; public class Test1 { public static void main(String[] args) { //两个携带不同泛型类型的类相比较 List<String> listStr = new ArrayList<>(); List<Integer> listInt = new ArrayList<>(); System.out.println(listStr.getClass()==listInt.getClass()); //输出true } }
(2)当一个类携带不同类型的泛型参数时,他们依然被当做是同一个类处理,所以在静态方法、静态代码块、静态变量中不允许使用泛型参数;
(3)系统中不会真正生成泛型类,所以instanceof运算符后不能使用泛型类。