Java 集合 - 泛型
# 介绍
- JDK1.5 版本后出现,JDK1.7版本后
new Array<>()
可以省略类型,该<>
称为钻石运算符 - 本质:参数化类型,把类型作为参数传递
- 常见形式:泛型类、泛型接口、泛型方法
- 语法:成为类型占位符,表示一种引用类型,可以写多个逗号隔开
- 类型:都是引用类型,不能是基本数据类型
- 好处 1. 提高代码重用性 2. 防止类型转换异常,提高代码安全性
# 不使用泛型缺点
一般存入集合的都是相同类型的数据,但是不适用泛型,无法规定只能使用相同类型的数据,不便于管理。
# 泛型类、泛型接口
实例化时不指定类的泛型,默认为 Object 类型
ArrayList list = new ArrayList(); list.add(1); // 既可以添加 Integer 类型 list.add("abc"); // 也可以添加字符串类型等
1
2
3如果子类继承泛型的父类,不指定父类的泛型,则子类必须也是泛型
public class Demo1<T>{} class Demo2<T> extends Demo1<T>{} class Demo3 extends Demo1<Integer>{}
1
2
3不同的泛型的引用类型不可以互相赋值,不可重载
- 本质都是 Object 类型,只不过操作的数据规定指定类型,两者属于同级关系,无法进行多态,只有子才能转为父
public void test(ArrayList<String> a){ ArrayList<String> list1 = null; ArrayList<Integer> list2 = nulll; list1 = list2; // 编译就报错了 }
1
2
3
4
5
6泛型类的静态方法不允许出现类的泛型
- 因为静态修饰的东西会优先类加载到内存中,但是此时泛型还没有指定是什么类型,所以报错
public class Demo1<T>{ public static void test(T t){} // 报错 }
1
2
3不能直接使用 T[] 创建数组
T[] t = new T[5]; // 报错 T[] t = (T[]) new Object[5]; // 这样可以,实际就是 Object 类型的数组,不是你要传入的类型数组
1
2
# 泛型方法
不是带泛型的方法就是泛型方法
方法的泛型和类的泛型无关
需要在返回值前加入泛型符号,与参数的泛型符号一致,否则参数的泛型符号默认为某个类的名字,但是该类不可能存在
public class Demo<T>{
// 不是泛型方法
public void a(T t){}
// 是泛型方法
public <E> void a(E e){}
}
1
2
3
4
5
6
2
3
4
5
6
泛型方法的静态方法允许出现类的泛型
因为静态修饰的东西会优先 类,但是不优先 方法 加载到内存中,所以方法可以加泛型,调用方法再传入泛型
public class Demo1<T>{ public static <E> void test(E e){} // 报错 }
1
2
3
# 通配符?
? 是泛型的通配符,可以解决互相赋值,重载问题
使用了通配符,遍历时候使用 Object 获取数据
public void test(ArrayList<String> a){ ArrayList<String> list1 = null; ArrayList<Integer> list2 = nulll; list1 = list2; // 编译就报错了 ArrayList<?> list3 = null; // ? 为通配符,可以认为属于所有泛型的父类 list3 = list1; // 成功 } public void test(ArrayList<Integer> a){ // 报错,因为泛型本质都是 Object,所以参数类型一样,不是重载,是复制 } public void test(ArrayList<?> a){ // 不会报错,因为?是泛型的通配符,所以参数类型不一样,是重载 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16使用通配符,无法添加数据,因为此时不知道泛型的类型是什么
可以获得数据,根据 Object 获取
public void test(){ ArrayList<?> list = new ArrayList<>(); // ? 为通配符,可以认为属于所有泛型的父类 list.add("abc"); // 报错,因为此时的 list 不属于任何类型 Obejct value = list.get(1); // 可以,Object 是所有类的父类 }
1
2
3
4
5
6
7
8
# 泛型受限
上限(? extends XX):只接受 XX 以及 XX 的子类及以下
下限(? super XX):只接受 XX 以及 XX 的父类及以上
class Person(){}
class Student(){}
public class test(){
public static void main(String[] args){
// List 本质属于 Object,并列关系,无法彼此直接赋值
List<Person> person = new ArrayList<>();
List<Student> student = new ArrayList<>();
// 泛型上限,只接受 Person 以及 Person 的子类及以下
List<? extends Person> list1 = null;
list1 = person;// 可以
list1 = student;// 可以,因为student属于Person的子类
// 泛型下限,只接受 Person 以及 Person 的父类及以上
List<? super Person> list2 = null;
list2 = person; // 可以
list2 = student; // 不可以,报错
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#
编辑此页 (opens new window)
更新时间: 2024/11/02, 18:07:00