提示:泛型的好处、泛型的用途、泛型的demo、泛型中的通配符有哪些
前言
今天准备提取出来一个工具类的时候,才猛然意识到,自己对java基础中的泛型可能没有想象中的那么熟悉。因此就总结了一下,同时也方便了后续的查阅。本人水平有限,如有误导,欢迎斧正,一起学习,共同进步!
一、泛型的好处
泛型是用来保护数据类型的安全。他的好处有
1、节省了来回转换的开销
2、避免了一些错误,比如不指定泛型,list里面同时存着int、boolean的数据,相加的时候,就会报错
二、泛型的用途
泛型的用途有:
- 含有泛型的类、
- 含有泛型的方法
- 含有泛型的接口
- 含有泛型的通配符:当使用泛型类或者方法时,传递的数据中,泛型类型的值不确定,可以通过通配符<?>表示,但是一旦使用泛型的通配符以后,只能使用Object类的共性方法,集合中元素的自身方法无法使用。
List : 该容器类型是Object的
List <?> : 该容器的数据类型可以是任意的
? : 通配符,不确定类型,代表该集合中可以存储任意类型的数据
? extend E : 限定了上限。E以及E的子类
? super E : 限定了下线,E以及E的父类
三、代码示例
1、含有泛型的类的代码:
注意,这里的T,是可以随便写的。只要是大写字母,ABCDEFG… 都可以的,这里是为了见名之意,是用的Type的T,有的源码(Collection的源码的泛型是E)中是E,代表element元素
代码如下(示例):
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Point<T> {
private T x;
private T y;
}
测试类:
public static void main(String[] args) {
// 创建对象的时候,才确定了泛型的类型
Point<Integer> point = new Point<>();
point.setX(1);
// 此时,只能set Integer类型的数据
point.setY(123);
System.out.println("=====================");
Point<String> point1 = new Point<>();
// 此时,只能set String类型
point1.setY("test");
}
2、含有泛型的方法
代码如下(示例):
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Point<T> {
// 定义泛型的方法
public static <M> void consolePrint(M m){
System.out.println("泛型的M的值:"+m);
System.out.println("泛型的M是String类型吗?:"+(m instanceof String));
}
}
测试类
public static void main(String[] args) {
// 测试泛型的方法
Point.consolePrint("hello world");
Point.consolePrint(new User());
}
3、含有泛型的接口
真正实现这个接口的时候,才知道具体的实现类型(泛型)是啥。
3.1、单个泛型
接口:
// 定义泛型的接口
public interface Door <A>{
A getType();
}
实现:
class DoorImplA implements Door<Integer>{
// 注意,泛型是Integer,返回就是Integer
@Override
public Integer getType() {
return null;
}
}
class DoorImplB implements Door<String >{
// 注意,泛型是String,返回就是String
@Override
public String getType() {
return null;
}
}
3.2、多个泛型
当然, 泛型是可以有多个的,比如:
// 定义泛型的接口
public interface Door <A,B>{
A getType();
B getTypeB();
}
class DoorImplA implements Door<Integer,String >{
// 注意,泛型是Integer,返回就是Integer
@Override
public Integer getType() {
return null;
}
@Override
public String getTypeB() {
return null;
}
}
class DoorImplB implements Door<String, User>{
// 注意,泛型是String,返回就是String
@Override
public String getType() {
return null;
}
@Override
public User getTypeB() {
return null;
}
}
4、含有泛型的通配符
class Son extends User{};
public class Demo2 {
// 这里可以放任意类型的
public static void test1(List<?> list){
}
// 这里只可以放Object类型的
public static void test2(List<Object> list){
}
public static void main(String[] args) {
List<User> list1 = new ArrayList<>();
List<Son> list2 = new ArrayList<>();
List<Object> list3 = new ArrayList<>();
// test1中,都可以放list1、2、3
test1(list1);
test1(list2);
test1(list3);
// test2中只可以放test3
test2(list3);
}
}
测试类
package com.zheng.genericity;
import com.zheng.entity.Teacher;
import com.zheng.entity.User;
import java.util.ArrayList;
import java.util.List;
/**
* @author: ztl
* @date: 2024/03/06 22:51
* @desc:
*/
class Son extends User{};
public class Demo2 {
// 这里可以放user和user的子类
public static void test1(List<? extends User> list){
}
// 这里只可以放user、user的父类
public static void test2(List<? super User> list){
}
public static void main(String[] args) {
List<User> list1 = new ArrayList<>();
List<Son> list2 = new ArrayList<>();
List<Object> list3 = new ArrayList<>();
// test1中,只可以放User和user的子类
test1(list1);
test1(list2);
// test2中只可以放user和user的父类
test2(list3);
}
}
总结
泛型到这里就结束了。祝大家五一快乐!