有时候我们会在业务中进行泛型设计的扩展。其中用的比较多的就是T , ?
泛型就相当于标签
形式:<>
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,
JDK1.5之 后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。
Collection<E>, List<E>, ArrayList<E> 这个<E>就是类型参数,即泛型。
结论:'T'指的是某一类具体的对象,'?'可以表示成占位符,表明多种数据类型;
示例:可以看到show1方法中我们使用了T,大家都知道这是泛型的常见写法,那么这里的T指的是某一类具体的对象,list集合里只能存放同一类型数据,如果插入不同类型数据则会报错。
那么show2方法中我们使用的是?,可以看到在void前面并没有<T>,?可以表示成占位符,它自己也不知道list集合中会存放多少种类型的数据,所以这样就表明我们的list中存放N种数据类型也是可以的。
我们通过一段测试代码来直观的感受一下二者的区别吧:
public static <T> void show1(List<T> list){
for (Object object : list) {
System.out.println(object.toString());
}
}
public static void show2(List<?> list) {
for (Object object : list) {
System.out.println(object);
}
}
public static void test(){
List<Student> list1 = new ArrayList<>();
list1.add(new Student("zhangsan",18,0));
list1.add(new Student("lisi",28,0));
list1.add(new Student("wangwu",24,1));
//这里如果add(new Teacher(...));就会报错,因为我们已经给List指定了数据类型为Student
show1(list1);
System.out.println("************分割线**************");
//这里我们并没有给List指定具体的数据类型,可以存放多种类型数据
List list2 = new ArrayList<>();
list2.add(new Student("zhaoliu",22,1));
list2.add(new Teacher("sunba",30,0));
show2(list2);
}
实际应用下:
分页响应对象类中返回的数据,我们可以定义为List<?> rows, 这里就不用T , 因为我们的类PageResult类没有定义泛型。 如果要写泛型T,是表示一个具体的属性,你需要在类上也声明好泛型T,这样在构建类的对象的时候,才能给泛型指定上具体的类型。
package com.tree.community.common.core.domain.page;
import org.apache.poi.ss.formula.functions.T;
import java.io.Serializable;
import java.util.List;
/**
* @Description **分页数据统一封装响应对象**
* @Author tree
* @Date 2024/4/29 16:44
*/
public class PageResult implements Serializable {
private static final long serialVersionUID = -6529723591699684110L;
/** 总记录数 */
private long total;
/** 列表数据 */
private List<?> rows;
/** 消息状态码*/
private int code;
/** 消息内容*/
private String msg;
public PageResult() {
}
public PageResult(long total, List<T> rows) {
this.total = total;
this.rows = rows;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public List<?> getRows() {
return rows;
}
public void setRows(List<?> rows) {
this.rows = rows;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
比如下面的 响应结果类,用了泛型T, 类上也需要带上
package com.tree.community.common.core.domain;
import java.io.Serializable;
/**
* @Description 响应结果封装对象
* @Author tree
* @Date 2024/4/28 17:41
*/
public class BaseResponse<T> implements Serializable {
private static final long serialVersionUID = -663626254744569433L;
/**自定义状态码**/
private String code;
/**自定义描述**/
private String message;
/**返回的数据**/
private T data;
/**
* 成功返回
* @param data
* @param <T>
* @return
*/
public static <T> BaseResponse<T> success(T data){
BaseResponse<T> response = new BaseResponse<>();
response.setCode(ResultCode.SUCCESS.getCode());
response.setMessage(ResultCode.SUCCESS.getMessage());
response.setData(data);
return response;
}
/**
* 失败返回
* @param message
* @param <T>
* @return
*/
public static <T> BaseResponse<T> fail(String message){
BaseResponse<T> response = new BaseResponse<>();
response.setCode(ResultCode.ERROR.getCode());
response.setMessage(message);
return response;
}
/**
* 失败返回
* @param code
* @param message
* @param <T>
* @return
*/
public static <T> BaseResponse<T> fail(String code, String message){
BaseResponse<T> response = new BaseResponse<>();
response.setCode(code);
response.setMessage(message);
return response;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
深入理解泛型(经典详解):<T> T 和 T的使用以及public <E> List<E> get()泛型方法详解、类型擦除、通配符的使用、泛型类的应用、泛型之间的继承_泛型t-CSDN博客