Java 泛型
https://www.bilibili.com/video/BV1Kb411W75N
泛型的概念
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。
例如,Arraylist,当不指定泛型时可以传入任意类型的值,但我们想固定它里面装的数据的类型,就可以使用泛型:ArrayList,这里的
在集合中使用泛型
import java.util.*;
public class GenericTest {
public static void main(String[] args) {
GenericTest genericTest = new GenericTest();
genericTest.test3();
}
// 在集合中使用泛型之前的情况:
public void test1() {
ArrayList list = new ArrayList();
// 需求:存放学生的成绩
list.add(78);
list.add(76);
list.add(89);
list.add(88);
// 问题一:类型不安全
// list.add("Tom");
for (Object score : list) {
// 问题二:强转时,可能出现ClassCastException
int stuScore = (int) score;
System.out.println(stuScore);
}
}
// 在集合中使用泛型的情况:以ArrayList为例
public void test2() {
ArrayList list = new ArrayList();
list.add(78);
list.add(87);
list.add(99);
list.add(65);
// 编译时就会进行类型检查,保证数据的安全
// list.add("Tom");
// 方式一:
// for (Integer score : list) {
// // 避免了强转操作
// int stuScore = score;
//
// System.out.println(stuScore);
// }
// 方式二:
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
int stuScore = iterator.next();
System.out.println(stuScore);
}
}
}
总结:
- 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
- 在实例化集合类时,可以指明具体的泛型类型。
- 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化时的泛型类型。
比如:add(E e) => 实例化以后:add(Integer e) - 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
- 如果实例化时,没有指明泛型的类型。默认类型为 java.lang.Object 类型。
自定义泛型结构
自定义泛型类和泛型接口
定义泛型类:public class Order
定义泛型接口:public interface aa
定义完泛型类和泛型接口后,其内部结构就可以使用相应的泛型。
注意点:
- 泛型不同的引用不能相互赋值
- 静态方法中不能使用类的泛型
- 异常类不能声明为泛型类
自定义泛型方法
泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。
泛型方法和所属的类是不是泛型类也没有关系
泛型方法可以声明为静态。原因:泛型参数是在调用方法时确定的,并非在实例化类时确定。
声明泛型方法举例:
public static List copyFromArrayToList(E[] arr) {
ArrayList list = new ArrayList<>();
for (E e : arr) {
list.add(e);
}
return list;
}
泛型的其它注意点
泛型与类的继承
若A是B的父类:
A
泛型通配符
若A是B的父类,G和G二者共同的父类是G<?>(通配符)。
使用通配符后的集合无法写入数据,只能写入null。可读取数据,但读取出来的数据类型是Object。
有限制条件的通配符
<? extends Person>: ≤ Person 类
<? super Person>: ≥ Person 类