Java 泛型: T和?的使用和区别
一.定义
T表示泛型,代表一种数据类型
?是通配符,表示不确定的数据类型
jdk为了便于理解,K代表键,V代表值,E代表枚举类型,T代表数据类型,这四个都是符号,只是表示了泛型的名称,换成其他字母也没问题,只不过要提前声明。
二.使用
通常得先在类里面声明了这个泛型
方法里面的参数就可以用泛型来表示了
< T extends Record>
< ? extends Record>
表示的是 限制 T , ? 类型 必须是Record的本类或者子类
注意:继承的父类或者是实现的接口里面的参数都必须是一个具体的类型
/**
*
* @param <T> Report record class
* @param <C> Report context class
*/
public abstract class CrystalReportDataPrepare<T extends Record, C extends CrystalReportContext> implements DataPrepare<C> {
@Override
public ReportData prepareData(C reportContext) {
return getCrystalReportData(reportContext);
}
private CrystalReportData getCrystalReportData(C reportContext) {
CrystalReportData crystalReportData = new CrystalReportData();
ReportParams reportParams = reportContext.getReportParams();
crystalReportData.setRecordList(getRecordList(reportContext));
crystalReportData.setRecordListGenericClass(getRecordListGenericClass());
crystalReportData.setAdditionalProperties(getAdditionalProperties(reportContext));
crystalReportData.setAsOfDate(reportContext.getAsOfDate());
crystalReportData.setReportTitle(reportParams.getTitle());
crystalReportData.setFileName(reportParams.getName());
String resetCompanyName = reportContext.getCompanyName();
if (CharSequenceUtil.isNotBlank(resetCompanyName)) {
crystalReportData.setCompanyName(resetCompanyName);
}
return crystalReportData;
}
private Class<T> getRecordListGenericClass() {
Class<?>[] clazzArray = GenericTypeResolver.resolveTypeArguments(this.getClass(), CrystalReportDataPrepare.class);
if (Objects.isNull(clazzArray)) {
return null;
}
return (Class<T>) clazzArray[0];
}
protected abstract List<T> getRecordList(C reportContext);
protected Map<String, Object> getAdditionalProperties(C reportContext) {
return new HashMap<>();
}
}
public static void test(){
List<Student> list1 = new ArrayList<>();
list1.add(new Student("张三",18));
//这里如果add(new Teacher(...))就会报错,因为我们已经给List指定了数据类型为Student
//这里我们并没有给List指定具体的数据类型,?泛指可以存放多种类型
List<?> list2 = new ArrayList<>();
list2.add(new Student("李四",20));
list2.add(new Teacher("王五",40));
}
如果有泛型方法和非泛型方法,同事都满足条件,则执行非泛型方法
public void show (String S) {
System.out.println("非泛型show");
}
public void show (T s) {
System.out.println("泛型show");
}
三.区别
使用场景:
<T> :声明一个泛型类或者泛型方法,代表的是某一种具体的数据类型
<?>:使用泛型类或者泛型方法(更多是使用在方法体里面),代表的是泛指所有的对象类型
public <T> List<T> getList(){
//错误,传入T的参数给ArrayList,返回的结果也应该是T类型的
List<?> list = new ArrayList<T>();
//因为ArrayList必须是一种类型,得到的也是同一种类型
List<?> list = new ArrayList<?>();
//正确
List<T> list = new ArrayList<T>();
return list;
}