为什么需要泛型Generic
假设一个需求
创建一个类,来打印Integer变量
普通方式完成需求
- 新建一个
IntegerPrinter
类
public class IntegerPrinter {
Integer content;
public IntegerPrinter(Integer content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
- main中测试
IntegerPrinter printer = new IntegerPrinter(114514);
printer.print();
输出
114514
问题
此时,如果又有一个打印字符串变量的需求,就需要重写建一个StringPrinter
,新增加其他类型有需要创建其他类型的Printer。
这样代码会有很多重复性,所以引入Generics泛型的概念:
只要创建一个类,就能处理所有类型
泛型标记符
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
- ? - 表示不确定的 java 类型
Generic 参数类型约束
在尖括号(Angle Brackets)加泛型标记符:<泛型标记符>
用Generic方式完成上述需求
- 新建一个Printer处理所有类型的变量
public class Printer<T> {
T content;
public Printer(T content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
- main中测试
Printer<Integer> integerPrinter = new Printer<>(114514);
Printer<String> stringPrinter = new Printer<>("Hi printer!");
integerPrinter.print();
stringPrinter.print();
输出
114514
Hi printer!
多个参数
public class Printer<T, K> {
T content1;
K content2;
public Printer(T content1, K content2) {
this.content1 = content1;
this.content2 = content2;
}
public void print(){
System.out.println(content1+content2);
}
}
Bounded Generic
- 可以通过
<T extends 父类>
来约束,规定T
必须是该父类的子类 - 可以通过
<T extends 接口>
来约束,规定T
必须是该接口的实现类 - 可以通过
<T extends 父类 & 接口>
来约束,规定T
必须是该父类的子类,并且是该接口的实现类(class必须在Interface前面)
Collection : Java中Generic类型约束的常见应用
List<Object> list = new ArrayList<>();
list.add("hello world");
list.add(1234);
System.out.println(list); // 不建议这么做,会有类型安全问题
输出
[hello world, 1234]
类型安全 Type-Safe
泛型在编译阶段进行类型检查,而不是运行时,有时候编译时不会出错,但运行时会,比如
List<Object> list = new ArrayList<>();
list.add("hello world");
list.add(1234);
String item = (String) list.get(1);
System.out.println(item);
上述代码在IDE并不会报错,但运行时会出错
Generic Method 泛型函数
泛型在函数上的应用,在返回类型之前加一个<T>
这样会报错:Cannot resolve symbol 'T'
// private static void print(T content){
// System.out.println(content);
// }
private static <T> void print(T content){
System.out.println(content);
}
也可以通过Bounded Generic约束
Wildcard 通配符
为什么需要通配符
- 比如打印一个
List<Integer>
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(123);
list.add(456);
print(list);
}
private static void print(List<Integer> content){
System.out.println(content);
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/e80b628910505aad1379d0850ffe91f8.png)
![img](https://img-blog.csdnimg.cn/img_convert/91ed595ad46220954919e509749720c2.png)
![img](https://img-blog.csdnimg.cn/img_convert/91f884b67f4e6c0f47438c3155219648.png)
![img](https://img-blog.csdnimg.cn/img_convert/e94dc0d10e5c90a5b2571ee14563af37.png)
![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)**
ps://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)**
![](https://img-blog.csdnimg.cn/img_convert/957ea1f103c43253ab67c872d68377fe.jpeg)