定义类,接口,方法时,可以用<>在编译阶段确定多种数据类型。
分为泛型类、泛型接口、泛型方法
//没有使用泛型 可以添加一切类型数据
ArrayList list1 = new ArrayList();
//使用了泛型 只能接受String类型的数据
//ArrayList<String> list2= new ArrayList<String>();
ArrayList<String> list2= new ArrayList<>();//jdk 1.7后后面可以不声明
泛型的原理
在声明泛型后,将<类型>传给了<E>,让这个只能接受和返回对应类型的数据。
泛型类
格式
//类型变量可以是任何字母 主要是表达一个可变参数
修饰符 class 类名 <类型变量, 类型变量>{
}
示例
public class MyArrayList<E> {
private Object[] arr = new Object[10];
private int size;
public boolean add(E e){
arr[size++] = e;
return true;
}
public E get(int index){
//alt + enter 强制类型转换
return (E) arr[index];
}
}
泛型接口
(保存数据和根据索引查询数据用)
public interface Container<E>{
public void add(E item); // 添加一个E
E get(int index); // 根据索引获得某个E
E remove(int index);// 根据索引删除某个E
}
泛型方法
// 泛型方法可以在方法返回类型之前声明类型参数。
public class lister {
public static void main(String[] args) {
String[] Stringlist={"1","b","e"};
Integer[] intlist={1,2,3};
printArray(Stringlist);
printArray(intlist);
}
public static <E> void printArray(E[] list){
for(E e : list){
System.out.print(e+" ");
}
System.out.println();
}
}
使用泛型方法,可以建立数据通用的缓存池,并对不同类型的数据进行处理。
通配符
通配符用于处理类型不确定的情况,如处理具有不同类型参数的集合。
public void printList(List<?> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
限制类型参数
通过使用 ?、extend 和 super 关键字,可以限制泛型类型参数的范围,以增强泛型安全性
通配符主要有三种类型:
无限制通配符(?)
上界通配符(A extends B)
保证获取的对象是B或者是B的子类,适用于读取数据的场景,保证至少是B类型
如:接受Number类型或其子类
下界通配符(A super B)
保证获取的对象是B或者是B的父类,适用于写入数据的场景,保证至少是B类型
如:写入Interger类型或其父类
// 上界通配符
public void printNumber(List<? extends Number> list){
// 只接受存入Number类型及其子类的list集合。
}
// 下界通配符
public void addNumber(List<? super Integer> list){
// 只接受写入Integer类型及其父类的list集合
}
总结
泛型的好处:
类型安全:在编译时进行类型检查,减少运行时类型错误。
消除强制类型转换:不需要显式的类型转换,提高代码可读性。
代码重用性:通过泛型,可以编写与类型无关的通用代码。