三、泛型
# 三、泛型
# 1、什么是泛型?作用是什么?
Java 泛型(Generics) 是 JDK 5 中引入的一个新特性。
泛型是一种参数化类型的机制,它允许在定义类、接口和方法时使用类型参数。通过泛型,可以编写与特定类型无关的代码,使得代码具有更广泛的适用性和重用性。
具体体现在以下方面
- 类型安全:泛型通过在编译时进行类型检查,可以在编译阶段发现类型不匹配的问题,减少了运行时出现类型转换异常的可能性,提高了程序的健壮性。
- 代码重用: 通过使用泛型,可以编写更加通用的算法和数据结构,使得它们可以适应不同的数据类型,从而提高了代码的重用性。
- 简化编码: 使用泛型可以减少重复代码的编写,提高代码的可读性和可维护性。你可以编写一个泛型类或方法,在需要时指定具体的类型参数,
而不需要为每种类型都编写一个新的类或方法。 - 性能提升: 泛型在编译时会执行类型擦除(Type Erasure)以确保向后兼容性,这种擦除可以提高代码执行时的性能。
例如: 编写一个盒子类 使用泛型 允许向盒子内添加任何类型
public class Box<T> {
private T content;
public Box(T content) {
this.content = content;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
public void printContentType() {
System.out.println("盒子里装的是:" + content.getClass().getName());
}
}
再比如集合中使用的泛型
ArrayList<User> userList = new ArrayList<>();
规定集合中只能存放User类型 以确保类型安全和编码的清晰性
# 2、泛型的使用方式有哪些?
泛型一般的使用方式:
- 泛型类
- 泛型接口
- 泛型方法
- 类型通配符
泛型类示例:
代码中的T 表示泛型 可以用任意的大小写字母代替 建议使用 T、V、K等字符
class Box<T>{
T data;
public Box(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public void printData(){
System.out.println(data.toString());
}
}
泛型接口示例:
public interface BaseMapper<T> {
public T get(String id);
}
// 实现泛型接口 指定类型
public class MyMapper<T> implments BaseMapper<User>{
@Override
public User get(String id){
retrun new User();
}
}
// 实现泛型接口 不指定类型
public class MyMapper<T> implments BaseMapper<T>{
@Override
public T get(String id){
retrun null;
}
}
泛型方法:
public static <K extends Comparable, V extends Comparable> Map<K, V> sortMapByValues(Map<K, V> aMap,long limitSize) {
HashMap<K, V> finalOut = new LinkedHashMap<>();
aMap.entrySet()
.stream()
// 排序
.sorted((p1, p2) -> p2.getValue().compareTo(p1.getValue()))
// 截取前limitSize个
.limit(limitSize)
.collect(Collectors.toList()).forEach(ele -> finalOut.put(ele.getKey(), ele.getValue()));
return finalOut;
}
类型通配符示例:
类型通配符:<?>
List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中类型通配符上限:<? extends 类型>
List<? extends Number>:它表示的类型是Number或者其子类型类型通配符下限:<? super 类型>
List<? super Number>:它表示的类型是Number或者其父类型举例:
// 这里的返回值 必须是 BaseRowModel类型 或者其子类型
public static <T extends BaseRowModel> ExcelWriterFactory writeExcelWithSheets(OutputStream outputStream,
Class<T> clazz) {
return new ExcelWriterFactory(outputStream, clazz);
}
# 3、项目中哪些地方使用到了泛型?
①、Mybatis的通用Mapper接口
public interface QguBaseMapper<T extends BaseModel> extends Mapper<T> {
}
②、通用的持久化接口
public interface MybatisService<T extends BaseModel> extends BaseService<T> {
Page<T> search(T model, Page<T> pageInfo, String... orders);
Page<T> search(Example example, Page<T> pageInfo, String... orders);
}
通用的导出功能抽象类
public abstract class AbstractBaseExportServiceImpl<T extends BaseModel> extends BaseServiceImpl<T> implements BaseExportService<T> {
// ...
}
③、各种通用的Util工具
总而言之 如果想让代码获得良好的重用性 使用泛型是一个非常重要的手段