Fork me on GitHub

反射加强(一)

1. 反射泛型信息

abstract class A<T> {
    // 无参构造器
    public A(){

        // 在这里获取子类传递的泛型信息, 要得到一个 Class!

        Class clazz = this.getClass(); // 得到子类的类型

        // 获取传递给父类参数化类型
        Type type = clazz.getGenericSuperclass();

        // 将 Type 类型转换为 ParameterizedType
        // 它就是对应的 A<String> 或 A<Integer>
        ParameterizedType pType = (ParameterizedType)type;

        // 获取泛型信息, 它是一个 Class 数组
        Type[] types = pType.getActualTypeArguments();

        Class c = (Class)types[0];  // 它就是 String 或 Integer
    }
}

class B extends A<String>{

}

class C extends A<Integer>{

}

2. 反射注解

2.1 要求
  • 注解的保留策略必须是 RUNTIME
2.2 反射注解需要从作用目标上返回
  • 类上的注解,需要使用 Class 来获取;
  • 方法上的注解, 需要使用 Method 来获取;
  • 构造器上的注解,需要使用 Constructor 来获取;
  • 成员上的注解,需要使用 Field 来获取.
  • 其中 Method, Constructor, Field 有共同的父类 AccessibleObject.
// 反射注解
public class Demo{

    // 获取 A 类上的 MyAnno2 注解
    public void fun(){
        // 1. 得到作用目标
        Class<A> c = A.class;

        // 2. 获取指定类型的注解
        // 该注解的保留策略必须是 RUNTIME
        MyAnno2 myAnno2 = c.getAnnotation(MyAnno2.class);

        System.out.println(myAnno2.name()+","+myAnno2.age()+","+myAnno2.sex());
    }

    // 获取 fun1 方法上的 MyAnno2 注解
    public void fun2(){
        // 1. 得到作用目标
        Class<A> c = A.class;
        Method method = c.getMethod("fun1");

        // 2. 获取指定类型的注解
        MyAnno2 myAnno2 = method.getAnnotation(MyAnno2.class);
    }
}

@MyAnno2(name="A类",age=23,sex="男")
@MyAnno3(age=25)
class A {
    @MyAnno2(name="fun1方法",age=24,sex="女")
    public void fun1(){
        ...
    }
}

// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno2 {
    String name();
    int age();
    String sex();
}

@interface MyAnno3{
    int age();
}

3. 反射泛型和注解的应用(初级Hibernate)

// BaseDao 将 dbUtils 升级

    public class Demo{
        private QueryRunner qr = new TxQueryRunner();

        // 添加用户
        public void addUser(User user){
            String sql = "";
            Object[] params = {   };
            qr.update(sql,params);
        }

        // 添加分类
        public void addCategory(Category category){
            String sql = "";
            Object[] params = {   };
            qr.update(sql,params);
        }
    }

class BaseDAO<T> {

    private QueryRunner qr = new TxQueryRunner();
    private Class<T> beanClass;

    // 无参构造方法
    public BaseDAO(){
        // 获取泛型的值,进而查询出表名
    beanClass = (Class)((ParameterizedType)this.getClass().getGenericSuperclass())
                    .getActualTypeArguments()[0];

    }

    /*
     *
     * public void add(T bean){
     *
     *     String sql = "insert into 表名 values(几个?)";
     *     Object[] params = {参数值是什么};
     *     qr.update(sql,params);
     * }
     */

    public void add(T bean){

        // 获取 T 类型中成员个数, 确定 values(参数个数)
        Field[] fs = beanClass.getDeclaredFields();


        // 如果规定表名和类名相同
        // 拼凑 sql 语句
        String sql = "insert into "+beanClass.getSimpleName()+" values (";
        for(int i=0; i< fs.length; i++){
            sql += "?";
            if(i < fs.length - 1){
            sql += ",";
            }    
        }
        sql += ")";
    }

    public void update(T bean){

    }

    public void delete(String uuid){

    }

    public T load(String uuid){
        return null;
    }

    public List<T> findALl(){
        return null;
    }
}


class UserDAO extends BaseDAO<User>{

    public void addUser(User user){
        super.add(user);
    }

}

参考资料:

posted @ 2017-10-16 20:50  小a的软件思考  阅读(329)  评论(0编辑  收藏  举报