泛型
泛型概述
泛型是JDK5引入的特性,可以在编译节点约束操作的数据类型,并进行检查
格式:<数据类型>
注意:泛型只能支持引用数据类型
如果没有给泛型定义数据类型,默认的是Object类型,此时可以添加任意类型的数据,在获取出来的时候,是不能使用子类的特有行为的(多态的弊端是不能访问子类的特有功能),如果进行强转,不知道强转成什么类型
泛型的好处
- 统一数据类型
- 把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来。
泛型的细节
- 泛型中不能写基本数据类型(因为基本数据类型不能转换成Object)
- 指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型
- 如果不写泛型,类型默认是Object
- 泛型只是在添加的时候加入了数据类型的校验,其实底层还是会变成Object去存储,在获取的时候在通过Object转成对应的类型。(可以去看编译后的class文件,里面的泛型都是转成了Object类型)
泛型类
使用场景:当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类,创建该类对象的时候,确定泛型
格式
修饰符 class 类名<类型>{}
1 2 3 4
| public class ArrayList<E>{ }
|
此处E可以理解为变量,但是不是用来记录数据的,而是记录数据的类型,可以写成:T、E、K、V等
泛型方法
方法中形参类型不确定时,
- 可以使用类名后面定义的泛型(类中所有方法都能用)
- 在方法申明上定义自己的泛型(只有本方法能用)
1 2 3 4 5 6 7
| public class MyArrayList<E>{ public boolean add(E e){ obj[size] =e; size++; return true; } }
|
格式
在修饰符后面定义方法,调用该方法的时候确定类型
修饰符<类型> 返回值类型 方法名(类型 变量名){}
1
| public <T> void show(T t){}
|
此处T可以理解为变量,但是不是用来记录数据的,而是记录数据的类型,可以写成:T、E、K、V等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public class ListUtil{ private ListUtil(){} public static<E> void addAll(ArrayList<E> list,E e1,E e2){ list.add(e1); list.add(e2); } public static<E> void addAll(ArrayList<E> list,E...e){ for(E e1:e){ list.add(e1); } } }
public class Demo{ public static void main(String[] args){ ArrayList<String> list1 = new ArrayList<>(); ListUtil.addAll(list1,"aaa","bbb"); } }
|
泛型接口
- 实现类给出具体类型
- 实现类延续泛型,创建对象时再确定
格式
在接口名后面定义泛型,实现类确定类型,实现类延续泛型
修饰符 interface 接口名<类型>{}
1
| public interface List<E>{}
|
1 2 3 4 5 6
| public class MyArrayList implement List<String>{} MyArrayList list = new MyArrayList();
public class MyArrayList2<E> implement List<E>{} MyArrayList2<String> list2 = new MyArrayList2<>();
|
泛型的继承和通配符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package com.zhuixun.demo;
import java.util.ArrayList;
public class fxDemo { public static void main(String[] args) {
ArrayList<Ye> list1 = new ArrayList<>(); ArrayList<Fu> list2 = new ArrayList<>(); ArrayList<Zi> list3 = new ArrayList<>();
method(list1);
}
public static void method(ArrayList<Ye> list){
} public static <E> void method(ArrayList<E> list){ } }
class Ye{} class Fu extends Ye{} class Zi extends Fu{}
|
泛型的通配符
关键点:可以限定类型的范围
- ?: 也可以表示不确定的类型,它可以进行类型的限定
- ? extends E: 表示可以传递E或者E所有的子类类型
- ? super E: 表示可以传递E或者E所有的父类类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package com.zhuixun.demo;
import java.util.ArrayList;
public class GenericsDemo {
public static void main(String[] args) { ArrayList<Ye> list1 = new ArrayList<>(); ArrayList<Fu> list2 = new ArrayList<>(); ArrayList<Zi> list3 = new ArrayList<>();
method(list1); method(list2); method(list3); }
public static void method(ArrayList<? extends Ye> list){} }
|
应用场景
- 如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口
- 如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以使用我们泛型的通配符