10.12JDBC之DAO实现类的优化

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的指向对象是谁

  • 通过反射获取到父类当中的泛型参数进行操作

  • 获取类型数组的第一个值

原文地址:https://www.cnblogs.com/JunkingBoy/p/15464324.html