10.12JDBC之DAO实现类的优化
固定的是操作Customer
表
原因:
-
固定操作的是
Customer
表,所以没必要在实现类当中每次都写一遍Customer.class
思路:
-
修改抽象类当中的
getInstance
方法,将形参class
改成获取父类的泛型。--->Java
基础当中的获取父类泛型的问题
解决办法:
-
因为操作的是指定的表,所以在方法当中加上泛型参数
-
public abstract class BaseDAO<T>/*这是将抽象的父类设置成泛型方法*/
-
-
在实现类当中在继承父类的时候给父类的泛型参数指明
JavaBean
对象-
public class CustomerDAOImpl extends BaseDAO<Customer> implements CustomerDAO/*在继承父类的时候指明泛型的JavaBean对象*/
-
此时可以在父类当中将泛型方法的
Class
参数进行删除了。后面要获取到父类当中的泛型参数-
public <T> List<T> getForList(Connection conn, String sql, Object ...args)
-
public <T> T getInstance(Connection conn, String sql, Object ...args)
-
-
-
方法当中需要使用到
Class
,而该Class
对象和实现类继承的父类当中的泛型对象一致。所以需要获取到当前实现类的父类的泛型 -
获取到的泛型是一个类型,让该类型给父类当中的
Class
做一个实例化-
在父类当中声明一个泛型
Class
-
/*
此时的泛型类型是父类的泛型,下面的方法不再是一个泛型方法。
去掉下面泛型方法的T,让这个T和父类当中的T保持一致
然后再给clazz做一个实例化
*/
private Class<T> clazz = null;
/*
实例化的对象:
取决于子类继承BaseDAO的时候父类(BaseDAO)的泛型是谁
相当于在子类中调用父类的属性进行一个复制
因为如果每一个子类都获取父类的泛型很浪费资源。所以写在父类中,通过继承和多态实现对属性clazz进行赋值
1、通过对象调用方法,所以需要在获取对象之前要有属性的赋值。出现对象之前可以给属性赋值的位置有:
1、显式赋值
2、代码块赋值
3、构造器赋值
*/
-
-
通过代码块的方式设置
clazz
属性的值-
//构造器赋值举例:
// public BaseDAO() {
//
// }
//使用非静态代码块对属性进行赋值。因为属性是非静态的属性。所以要写成非静态的代码块
{
//给clazz进行实例化
/*
1、确定该实例化操作执行时间--->new子类对象的时候会加载子类构造器,构造器当中有一个super()会去加载父类的结构。加载父类结构会先后加载:
1、父类的代码块
2、父类的构造器
在造子类对象的时候该代码块就会执行了。需要获取当前对象的父类的泛型
*/
//当前对象是this--->this不是指代书写的类,而是指实例化的类的对象,造了子类对象那么this一直是子类的对象
Type genericSuperclass = this.getClass().getGenericSuperclass(); //--->获取自己这个类的带泛型的父类
//带泛型了以后做一个强制转型--->因为父类的泛型带了参数,所以这是一个带了参数的Type
ParameterizedType paramType = (ParameterizedType) genericSuperclass;
Type[] typeArguments = paramType.getActualTypeArguments(); //--->获取了父类的泛型参数。泛型会有多个,所以返回的是一个数组
//因为只有一个参数,所以就是数组的第一个位置--->反射的时候提到
clazz = (Class<T>) typeArguments[0]; //--->这样就获取到了泛型的第一个参数,需要强制转型
}
-
-
难点:
-
Java
继承当中构造器再被实例化的时候执行方式的特点 -
this
的指向对象是谁 -
通过反射获取到父类当中的泛型参数进行操作
-
获取类型数组的第一个值