Java范型与反射

                              Java范型与反射

    Java的泛型是一种伪范型,意思是Java的范型其实只能在编译前有效,编译时编译器会擦除范型信息,因此也可能会出现一些范型导致的错误。

    下面是一段经典的获取类型的代码

package reflect_test;

/**
 * Created by dengxiaobing on 2018/6/9.
 */
public class Test<T> {
    public static void main(String[] args) {
        System.out.println(new Test<Number>().getClass());
    }
}

打印结果是

class reflect_test.Test

很明显,Java编译时已经把Test的范型参数Number擦除了


public static void main(String[] args) {
    System.out.println(new ArrayList<Integer>().getClass() == new ArrayList<String>().getClass());
}

这段代码的打印结果是true,表明Integer的List和String的List获取到的类类型是相同的,其实在编译后都是ArrayList<Object>,这就很尴尬了,有时候,我们确实想获取一个范型类的范型参数

这个时候,可以通过反射获取真正的范型参数

package reflect_test;


import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Created by dengxiaobing on 2018/6/9.
 */
public class Test<T> {

    private static class Parent<T>{

    }

    private static class Child extends Parent<Number>{

    }

    public static void main(String[] args) {
        Type type = Child.class.getGenericSuperclass();
        if (type instanceof ParameterizedType){
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type[] types = parameterizedType.getActualTypeArguments();
            for(Type t: types){
                System.out.println(t.getTypeName());
            }
        }
    }
}
 
 

打印结果是

java.lang.Number

想象一下应用场景,在JPA中,我们继承一个JpaRepository就可以实现增删改查的操作了,增和改还好,需要传入一个Entity对象,可以通过这个Entity对象获取到类类型,然后通过类类型获取到注解和属性,再和数据库表做个ORM映射,就可以完成ORM操作了,但如果是查和删的操作,传入的是一个id之类的字段值,要获取类类型就需要获取范型参数了。通过上面 代码那种方式,在JpaRepository中的delete和search方法中用main方法中的操作获取到类类型,因为是继承,根据多态原理,实际的调用对象是子类的对象。

下面做一下简单的实现

package reflect_test;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Created by dengxiaobing on 2018/6/11.
 */
public class JPA_Test {
    private static class JpaRepository<ID,Entity>{
        private Class getEntityClass(){
            Type type = this.getClass().getGenericSuperclass();
            if (type instanceof ParameterizedType){
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Type types[] = parameterizedType.getActualTypeArguments();
                return types.length>1?((Class)types[1]):null;
            }
            return null;
        }
        void delete(ID id){
            Class c = getEntityClass();
            Field[] fields = c.getDeclaredFields();
            for (Field field:fields){
                System.out.println(field.getName());
            }
        }

        Entity search(ID id){
            return null;
        }
    }



    private static class Student{
        private int id;
        private String name;
        private int age;
    }

    private static class StudentRepository extends JpaRepository<Integer,Student>{

    }

    public static void main(String[] args) {
        JpaRepository<Integer,Student> repository = new StudentRepository();
        repository.delete(0);
    }
}
 
 

打印结果

id
name

age

得到了我们想到的信息

用这种技术就可以实现类似JPA的一个ORM框架了











猜你喜欢

转载自blog.csdn.net/qq_31728311/article/details/80653171