Java反射理解

什么是Java反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为Java的反射机制。

反射提供的功能:

  • 运行时判断任意一个对象的类
  • 运行时构造任意一个类的对象
  • 运行时判定一个类具有的成员变量和方法
  • 运行时调用任意一个对象的方法
  • 动态代理

反射机制类:

  • java.lang.Class: 类
  • java.lang.reflect.Constructor : 构造方法
  • java.lang.reflect.Field : 类的成员变量
  • java.lang.reflect.Method : 类的方法
  • java.lang.reflect.Modifier : 访问权限

实现反射:

1. 获取Class对象:3种方式

Dog dog = new Dog("tom");
//1.通过对象获取
Class class1 = dog.getClass();
//2.通过类的属性获取
class1 = Dog.class;
//3.通过Class类的静态方法获取
try {
    class1 = Class.forName("Dog");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

2. 获取class对象的摘要信息:

//判断是否是基础类
class1.isPrimitive();
//java.lang.Boolean
//java.lang.Character
//java.lang.Byte
//java.lang.Short
//java.lang.Integer
//java.lang.Long
//java.lang.Float
//java.lang.Double
//java.lang.Void
//判断是否是集合
class1.isArray();
//判断是否是注解
class1.isAnnotation();
//判断是否是接口
class1.isInterface();
//判断是否是枚举
class1.isEnum();
//判断是否是匿名内部类
class1.isAnonymousClass();
//判断是否被某个注解类修饰
class1.isAnnotationPresent(Deprecated.class);
//获取内部类
Class[] innerClasses = class1.getDeclaredClasses();
//获取外部类
Class outClasses = class1.getDeclaringClass();

3. 获取class对象的属性,方法,构造函数等

class Base {
    public String age;
    public Base() {}
}

class Dog extends Base {
    private String name;
    protected String shortName;
    public Dog(String name) {this.name = name;}
    private Dog() {}
    public void displayName() {System.out.println(name);}
}

//所有public属性,包括从父类继承的
Field[] publicFields = class1.getFields();
//所有属性,只包括自身声明过得
Field[] allFields = class1.getDeclaredFields();
//所有公共方法,包括从父类继承的
Method[] publicMethods = class1.getMethods();
//所有方法,只包括自身声明过得
Method[] allMethods = class1.getDeclaredMethods();
//所有公共构造函数
Constructor[] publicConstructors = class1.getConstructors();
//所有构造函数,,只包括自身声明过得
Constructor[] allConstructors = class1.getDeclaredConstructors();

输出:
---publicFields---
public java.lang.String Base.age
---allFields---
private java.lang.String Dog.name
protected java.lang.String Dog.shortName
---publicMethods---
public void Dog.displayName()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
---allMethods---
public void Dog.displayName()
---publicConstructors---
public Dog(java.lang.String)
---allConstructors---
public Dog(java.lang.String)
private Dog()

4. class对象动态生成

try {
    //1. 调用Dog类的无参构造函数(这种方式需要确保无参构造函数不是私有的)
    obj = class1.newInstance();
    Constructor cs = class1.getDeclaredConstructor(new Class[]{String.class});
    //2. 调用有参构造函数
    obj = cs.newInstance(new Object[]{"tom's dog"});
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
    e.printStackTrace();
}

5. 动态调用函数

//获取方法对应的Method对象
Method method = class1.getDeclaredMethod("displayName");
//调用函数
method.invoke(obj);
//获取含参方法
Method method2 = class1.getDeclaredMethod("setName", new Class[]{String.class});
//调用函数并传递参数
method2.invoke(obj, new Object[]{"new name"});

6. 通过反射机制获取泛型类型

摘自:Java学习之反射机制及应用场景

//People类
public class People {}
//Person类继承People类
public class Person extends People implements PersonInterface {}
//PersonInterface接口
public interface PersonInterface {}

获取泛型类型

Person person = new Person<>();
//第一种方式 通过对象getClass方法
Class class1 = person.getClass();
Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类的 Type
Type[] interfaceTypes = class1.getGenericInterfaces();//获取class对象的所有接口的Type集合

getComponentType(genericSuperclass);
getComponentType(interfaceTypes[0]);

getComponetType:

private Class getComponentType(Type type) {
Class componentType = null;
if (type instanceof ParameterizedType) {
    //getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。
    Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
    if (actualTypeArguments != null && actualTypeArguments.length > 0) {
    componentType = (Class) actualTypeArguments[0];
    }
} else if (type instanceof GenericArrayType) {
    // 表示一种元素类型是参数化类型或者类型变量的数组类型
    componentType = (Class) ((GenericArrayType) type).getGenericComponentType();
} else {
    componentType = (Class) type;
}
return componentType;
}

7. 通过反射获取注解:

        Class melaClass = null;
        try {
            melaClass = (Class) Class.forName("Mela");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            //获取指定方法
            Method method = melaClass.getDeclaredMethod("setName", String.class);
            //获取所有注解
            Annotation[] annotations = method.getAnnotations();
            //获取类型指定注解
            Annotation annotationType1 = method.getAnnotation(Deprecated.class);
            //获取所有参数注解
            Annotation[][] paramsAno = method.getParameterAnnotations();
            for (Annotation[] aParamsAno : paramsAno) {
                for (Annotation anAParamsAno : aParamsAno) {
                    System.out.println(anAParamsAno);
                }
            }
            System.out.println(annotationType1);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        //获取所有成员变量的注解
        Field[] fields = melaClass.getDeclaredFields();
        for (Field f : fields) {
            Annotation[] annotations = f.getDeclaredAnnotations();
            for (Annotation a : annotations) {
                System.out.println(a);
            }
        }
    }

8. 反射机制的应用场景:

  • 逆向代码 ,例如反编译
  • 与注解相结合的框架 例如Retrofit
  • 单纯的反射机制应用框架 例如EventBus 2.x
  • 动态生成类框架 例如Gson

你可能感兴趣的:(Java反射理解)