泛型
在JDK 1.5 之前,编译器允许我们向容器插入不同类据的数据。例
/*
* 现在有一批 Apple
* 需求:对这一批产品核对 id 再出仓
*/
class Apple{
private static long counter;
private final long id = counter++;
public long id(){ return id; }
}
class Orange{}
public static void main(String[] ages){
List appleList = new ArrayList();
appleList.add(new Apple);
appleList.add(new Orange);
appleList.add(new Apple);
appleList.add(new Apple);
for(int i = 0; i < appleList.size(); i++){
(Apple)appleList.get(i).id();
}
}
在 appleList 集合中我们不小心加入了 Orange 类型的元素,因为ArrayList存放的中Object类型,在对 appleList 集合做遍历时,通过get(index) 方法返回的元素是Object类型的引用,所以要强转为Apple类型,又对每个元素都去调用了Apple中的 id() 方法,但 Orange 这个元素没有 id() 这个方法,所以程序在遍历到这个元素时会报错
要想让 ArrayList 只保存 Apple 类型,可以声明 ArrayList<Apple>
尖括号里面放的是类型参数,它指定了这个容器可以存放的类型。参数可以有多个,但要看容器是否支持。
这就是泛型,可以在编译期防止将错误的类型存放到容器中。而且从容器中取出时也不用再做类型转换,因为容器知道存储的是什么类型,在调用get()时替我们执行了转型
public static void main(String[] ages){
List<Apple> appleList = new ArrayList();
appleList.add(new Apple);
//appleList.add(new Orange);//提示错误
appleList.add(new Apple);
appleList.add(new Apple);
for(int i = 0; i < appleList.size(); i++){
(Apple)appleList.get(i).id();
}
}
还可以兼容向上转型,可以将Apple类型的子类型添加到被指定为Apple对象的容器中
public class Fuji extends Apple{}
public class Gala extends Apple{}
main:
List<Apple> appleList = new ArrayList();
appleList.add(new Apple());
appleList.add(new Apple());
appleList.add(new Apple());
appleList.add(new Fuji());
appleList.add(new Gala());
for (int i = 0; i < appleList.size(); i++) {
System.out.println(appleList.get(i));
}
/*
Apple@1b6d3586
Apple@4554617c
Apple@74a14482
Fuji@1540e19d
Gala@677327b6
*/
自定义泛型类
泛型类就是一个或多个类型变量的类。
自定义泛型类,类型变量放在类名的后面,用<>尖括括起来。可以有多个
class Pair<T>{
private T data;
public Pair(){this.data = null;}
public Pair(T data){ this.data = data; }
public T getData(){ return data; }
public void setData(T data){ this.data = data; }
}
类型变量使用大写形式,一般使用 E 表示集合的元素类型;K和V分别表示关键字和值;T(U,S)表示任意类型
自定义泛型方法
自定义泛型方法,类型变量放在修饰符的后面,也是用<>尖括括起来。可以有多个
class ArrayAlg{
public static <T> T getMiddle(T t){
return t[t.length / 2];
}
}
main:
String middle = ArrayAlg.<String>getMiddle("John");
在调用泛型方法时,在方法名前的尖括号内放入具体的类型
限定类型
在类中,如果定义了一个泛型对象,那么意义着它可以是任何类的对象。想它去调用指定的方法,但又不能确保这个泛型所属的类是否有这个方法时,可以将泛型限制为实现了有这个方法的接口的类,从而限定泛型类
public static <T> T getMiddle(T t){
return t.apple();
}
限定后的代码:
public static <T extends Apple> T getMiddle(T t){
return t.apple();
}
如果在调用方法时,给定的泛型不是实现Apple类,那么会产生编译错误。
也可以有多个限定,限定类型以 & 隔开:<T extends Apple & Minnex>
泛型机制是在编译阶段起作用,只是给编译器参考,在运行阶段没用。虚拟机中没有泛型对象,泛型可以看作是一个类型的占位符
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)