目录
1. 泛型类、泛型方法
类名<T>、类名<T, S> 泛型类的声明形式就是这样的,<>里面就是泛型类型变量,可以是一个,也可以是多个,用于代表任意一种类型。 建议:泛型类型变量用大写形式,且比较短,不一定非是一个大写字母,但是建议最好这样遵循,在java库中,使用E表示集合的元素类型,K和V分别表示映射的键与值类型,T表示任意类型。 举个例子:
public class HeHe<T, s, AAR> {
private T alice;
private s bob;
private AAR manry;
public HeHe(){}
public void prin(T content){
System.out.print(content);
}
public T getAlice() { return alice; }
public void setAlice(T alice) { this.alice = alice; }
public s getBob() { return bob; }
public void setBob(s bob) { this.bob = bob; }
public AAR getManry() { return manry; }
public void setManry(AAR manry) { this.manry = manry; }
public static void main(String[] args){
HeHe<String, Integer, Date> he = new HeHe<>();
he.setAlice("my name is alice");
he.setBob(12);
he.setManry(new Date());
}
}
泛型方法:将泛型类型变量紧挨着返回类型并放在返回类型的前面。比如:public <T> int getAa(){ }
泛型方法可以定义在普通类中,也可以定义在泛型类中,调用泛型方法时,在方法名前面的尖括号中放入具体类型
int var = <String>getAa();
但是泛型的使用需要注意:泛型可以是任意的类型,当需要比较的时候,如果具体的类型没有实现了Comparable接口的compareTo方法,那么就会报错或者得到一个不正确的结果。
解决方法: public <T extends Comparable> int getAa(){ }
2.泛型中extends 和 super的区别
这里只是针对没有使用强制类型转换的,在此基础上,才有下面的说明,如果使用强制类型转换,那下面的说明就不严谨了。
2.1 extends
类型的上界,只接收本身类或者其子类的引用赋值,比如List<? extends Fruit> list 如下。
只能接收取值,而不能插入值,因为List<? extends Fruit> list 可以接收的Fruit类或者子类,但是编译器不知道具体是哪个类。
只能list.add(null) 没有意义。
public class Fruit{}
public class Apple extends Fruit{}
public class Banana extends Fruit{}
//main方法
public static void main(String[] args){
List<? extends Fruit> list = new ArrayList<>();
//List<? extends Fruit> list = new ArrayList<Apple>(); 这样也行
//List<? extends Fruit> list = new ArrayList<Banana>(); 这样也行
//extends用法规定:只准取数据,不能存入数据,除非你用强制类型转换
}
2.2 super
类型的下界,只接受本身类或者其父类的引用赋值,比如List<? extends Fruit> list 如下。
只能插入值,不能获取值,插入值也只能时Fruit这个下界类本身或者下界类的子类对象,不能获取值是因为不知道获取到的对象属于哪个类,但是可以Object o = list.get(1); 这种方法类获取对象,但是Object类引用会丢失实际对象的所有值,没意义。
public class Food{}
public class Fruit extends Food{}
public class Apple extends Fruit{}
public class Banana extends Fruit{}
//main方法
public static void main(String[] args){
List<? extends Fruit> list = new ArrayList<Food>();
list.add(new Fruit());
list.add(new Apple());
//List<? extends Apple> list = new ArrayList<Food>(); 这样也行
//List<? extends Apple> list = new ArrayList<Fruit>(); 这样也行
//super用法规定:只准存入数据,不能取数据
}
3. 基本原理
泛型这个概念只停留在编译阶段,因为JVM是不认识泛型的,比如上文中定义了HeHe<T, s, AAR> 类,假如我们在某个代码中用到了,HeHe<String, Integer, Long> hehe = new HeHe<>(); 这样的话,编译器就会将根据具体的类型去将所有的泛型符号替换掉,如果HeHe hehe = new HeHe(); 是这样的话,那么就用Object去替换掉所有的泛型符号,这种替换就叫作“类型擦除”。
所以说,泛型只停留于编译阶段,编译完了后,就是实实在在的类型了。