泛型解读
出现在jdk1.5之后
一、泛型的作用:
- 可以减少手动类型转换工作
- 将类型转换提前到编码阶段
- 将程序运行时的错误提前到编码时报错
二、泛型语法:
1.泛型方法
代码段1:
@Test
public void test(){
//在这里需要类型强制转换
Cat cat= (Cat) save(new Dog(),new Cat());
}
public <T,K> Object save(T t,K k){
List<T> list=new ArrayList<>();
list.add(t);
return k;
}
代码段2:
@Test
public void test(){
//已经不需要类型转换,save()方法返回的是泛型K
Cat cat= save(new Dog(),new Cat());
}
/**
* 设计一个通用方法,可以接收任何类型
* 泛型方法的作用是可以让开发者设计出更加通用的方法
*
* @param t 传入的参数,任意类型
* @param k 传入的参数,任意类型
* @param <T> 定义的泛型 还可以这样<T extends Animal>
* @param <K> 定义的泛型 ...
* @return K泛型
*/
public <T,K> K save(T t,K k){
List<T> list=new ArrayList<>();
list.add(t);
return k;
}
对比结果:
代码段二类型转换提前至编码阶段
注意:泛型方法的类型确定:在调用方法时确定类型
2.泛型类
将泛型定义在类上
如果泛型类定义了泛型,那么如果方法上使用了同一类型,则方法就不需要再定义
class Demo<T,K>{
public K save(T t,K k){
List<T> list=new ArrayList<>();
list.add(t);
return k;
}
}
泛型类的类型确定:在创建类对象的时候确定类型
Demo<String,Cat> demo=new Demo<>();
3.泛型接口
interface IBaseDao<T> {
void save(T t);
void update(T t);
}
class Employee{
}
/**
* 通用业务dao
* @param <T>
*/
class BaseDao<T> implements IBaseDao<T>{
@Override
public void save(T t) {
//通用的action
}
@Override
public void update(T t) {
//通用的action
}
}
/**
* 具体的业务dao
*/
class EmpDao extends BaseDao<Employee>{
@Override
public void save(Employee e) {
//具体的action
}
@Override
public void update(Employee e) {
//具体的action
}
}
泛型接口的类型确定:
- 直接实现泛型接口的时候可以确定类型
- 继承泛型接口的实现类时可以确定类型
三、泛型关键字:
- ?
- extends
- super
作用:用于限定泛型的使用范围
?:如果一个泛型类加上?号泛型,则该类不能在进行编译,只能用于接收数据
List<?> list=new ArrayList<>();
//不可以再对list对象进行操作
extends:只能传入指定类的对象或者指定类的子类
public void add(List<? extends Number> list){
//action
}
@Test
public void test(){
List<Integer> intList=new ArrayList<>();
add(intList);
List<Float> floatList=new ArrayList<>();
add(floatList);
List<Double> doubleList=new ArrayList<>();
add(doubleList);
}
super:只能传入指定类的对象或者指定类的父类
public void add(List<? extends Number> list){
//action
}
@Test
public void test(){
List<Number> numberList=new ArrayList<>();
add(numberList);
}
四、反射泛型
1.bean类
public class Student {
private int id;
private String name;
private int age;
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
Getter and Setter...
}
public class Teacher {
private int id;
private String name;
private int age;
public Teacher(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
Getter and Setter...
}
2.BaseDao
public class BaseDao<T> {
private Class targetClass;//具体的dao上面的泛型类型
private final String tableName;//对应的表名
public BaseDao() {
//1.this: 代表当前运行的dao对象
Class clazz = this.getClass();
//2.clazz.getGenericSuperclass() :得到当前dao对象的父类(参数化类型)
Type type = clazz.getGenericSuperclass();//BaseDao<Teacher>
//3.把父类的类型强转成子类(参数化类型: ParameterizedType)
ParameterizedType param = (ParameterizedType) type;//BaseDao<Teacher>
//4.param.getActualTypeArguments():得到参数化类型上面的泛型类型列表
Type[] typeArguments = param.getActualTypeArguments();//<Teacher>
//5.取出泛型类型列表中的第一个泛型
Type target = typeArguments[0];//Teacher
//6.强制成Class类型
targetClass = (Class) target;//Teacher
//7.获取对应的表名
tableName = targetClass.getSimpleName().toLowerCase();
}
/**
* 查询全部
*
* @return
*/
public List<T> findAll() {
List<T> list = new ArrayList<>();
...
return list;
}
/**
* 查询指定ID的信息
*
* @param id
* @return
*/
public T findById(int id) {
...
return T;
}
}
3.具体的Dao,StudentDao、TeacherDao
public class StudentDao extends BaseDao<Student> {
@Override
public List<Student> findAll() {
return super.findAll();
}
@Override
public Student findById(int id) {
return super.findById(id);
}
}
public class TeacherDao extends BaseDao<Teacher> {
@Override
public List<Teacher> findAll() {
return super.findAll();
}
@Override
public Teacher findById(int id) {
return super.findById(id);
}
}
4.调用
StudentDao dao=new StudentDao();
List<Student> studentList=dao.findAll();
Student student= dao.findById(1);