Java 的反射

Java 反射

Java 反射是在 java.lang.reflect 包类,包含 Constructor、Method、Field 的反射。

涉及的方法 说明
创建类 Constructor Class.getConstructor( ) Constructor.newInstance(args) newInstance( ) 方法可以为无参调用
方法 Method Class.getMethods( ) Class.getDeclaredMethods( ) getMethods( ) 返回自身和父类的方法; getDeclaredMethods( ) 只返回自身的方法
变量 Field Class.getFields( ) Class.getDeclaredFields( ) getFields() 获取这个类和它父类的 public 成员变量; getDeclaredFields() 获取这个类和它父类的全部成员变量

1. 通过反射创建类 Constructor

无参构造

Class clazz = Class.forName("类的路径");
Constructor constructor = cl.getConstructor();
Object object = constructor.newInstance();

有参构造

Class classType = Class.forName(classPath);
Constructor constructor = classType.getConstructor(intArgsClass);
constructor.setAccessible(true);  // 压制 java 检查,防止当构造函数时 private 时拿不到
Object object = constructor.newInstance(intArgs);

说明

  • getConstructor(Class[])Class[] 是构造函数参数类型

例如 Employee(String name, long salary), 则 Class[] 就是 new Class[]{String.class, long.class}

  • onstructor.newInstance(Object[]) Object[] 是构造函数的具体参数值

例如 Employee(String name, long salary) 则 Object[] 就是 new Object[]{“张三”, 5000}

  • 如果是无参构造函数使用 Class.newInstance( ) 即可,可不用反射

例子

调用了无参构造函数
private Object createEmployeeByClassPath(String classPath){
    try {
        Class cl = Class.forName(classPath);
        Constructor constructor = cl.getConstructor();
        Object object = constructor.newInstance();
        return object;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
如果是 private 的构造函数
// 获取 private 的构造函数
Class cl = Class.forName(classPath);
Constructor constructor = cl.getDeclaredConstructor();
constructor.setAccessible(true);           
Object object = constructor.newInstance();
调用有参构造函数
private void createEmployeeByConstructor(String classPath, Class[] intArgsClass, Object[] intArgs){
    try {
        Class classType = Class.forName(classPath);
        Constructor constructor = classType.getConstructor(intArgsClass);
        constructor.setAccessible(true);  // 压制 java 检查,防止当构造函数时 private 时拿不到
        Object object = constructor.newInstance(intArgs);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2.通过反射调用方法 Method

获取方法

Class.getMethods() 返回自身和父类的方法
Class.getDeclaredMethods() 只返回自身的方法

获取指定的方法

// methodName 是方法名,intArgsClass 是方法签名参数类型
Method method = clazz.getDeclaredMethod(methodName, intArgsClass);  

调用方法

 method.invoke(Object, intArgs) // intArgs 是具体的参数类型

例子

获取方法
private void getMethods(Object object){
    // 获取所有方法,包括父类的
    Method[] methods = object.getClass().getMethods();
    for (Method method : methods){
        Log.i(TAG, "getMethods method " + method.toString());
    }

    // 至获取自身定义的方法
    Method[] methods1 = object.getClass().getDeclaredMethods();
    for (Method method : methods1){
        Log.i(TAG, "getMethods method " + method.toString());
    }
}
调用方法
// 反射调用方法
private void invokeMethod(Object object, String methodName, Class[] intArgsClass, Object[] intArgs){
    try {
        Class clazz =  object.getClass();
        Method method = clazz.getDeclaredMethod(methodName, intArgsClass);
        method.setAccessible(true);
        Object returnValue = method.invoke(object, intArgs);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3. 通过反射获取成员变量 Field

获取 Field

Fields[] fields = Class.getFields()  // 获取这个类和它父类的 public 成员变量
Fields[] fields = Class.getDeclaredFields()  //获取这个类和它父类的全部成员变量

设置成员变量的值

Class.getDeclaredField(fieldName) // 获取具体的成员变量
Field.setAccessible(true);
Field.set(object, value) // 设值

例子

获取成员变量
// 获取成员变量
private void getFields(Object object){
    Field[] fields = object.getClass().getFields();
    for (Field field : fields){
        Class type = field.getType();
        String name = field.getName();
    }
}
获取具体的成员变量
private void getField(Object object, String fieldName){
    try {
        Field field = object.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        Object fieldVale = field.get(object);
        String name = (String) fieldVale;
    } catch (Exception e) {
        e.printStackTrace();
    }
}
设置成员变量的值
private void setFieldValue(Object object, String fieldName, Object value){
    try {
        Field field = object.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(object, value);
    } catch (Exception e){
        e.printStackTrace();
    }
}

4. 获取注解

Metho, Field, Constructor 都可以直接调用getAnnotationgetAnnotation(Class<> annotationType) 获取

使用注解的开源库都会用到 EeventBus, ARouter 等

private void getAnnotationMethod(Object object){
    Method[] methods = object.getClass().getDeclaredMethods();
    for (Method method: methods){
        MyAnnotation annoType = method.getAnnotation(MyAnnotation.class);
        if (annoType != null){
            Log.i(TAG, "getAnnotationMethod name = " + method.getName());
        }
    }
}

5.获取修饰符

Metho, Field, Constructor 都可以直接调用 getModifier() 获取
Modifier 这个类可以分析这个返回值

private void getModifiers(Object object){
    Field[] fields1 = object.getClass().getDeclaredFields();
    for (Field field : fields1){
        Class type = field.getType();
        String name = field.getName();
        printModifier(name, field.getModifiers());
    }
}

private void printModifier(String name, int modifier){
    String modifiers = Modifier.toString(modifier);
    boolean isFinal = Modifier.isFinal(modifier);
}

6. 其他

setAccessible(true)

Metho, Field, Constructor 都可以设置 setAccessible(true), 压制 java 检查,防止 private 时拿不到

getConstructor 与 getDeclaredConstructor 的区别

  • getDeclaredConstructor 可以返回 private 的构造函数,但是需要 Constructor.setAccessible(true), 配合一起使用
Class cl = Class.forName(classPath);
Constructor constructor = cl.getDeclaredConstructor();
constructor.setAccessible(true);
Object object = constructor.newInstance();
  • getConstructor 只是返回 public 的构造函数
Class cl = Class.forName(classPath);
Constructor constructor = cl.getConstructor();
Object object = constructor.newInstance();

7.完整的示例代码

ReflectActivity.java

/**
 * 反射的
 */
public class ReflectActivity extends Activity {
    private static final String TAG = "ReflectActivity";

    private static final String CLASS_PATH = "com.yxhuang.myapplication.reflect.Employee";

    private Employee mEmployee;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_reflect);

//        createEmployeeByConstructor(CLASS_PATH, new Class[]{String.class, long.class}, new Object[]{"张三", 5000});


//        Object object =  createEmployeeByClassPath(CLASS_PATH);
//        getMethods(object);

//        invokeMethod(object, "setName", new Class[]{String.class}, new Object[]{"李四"});

//        mEmployee = new Employee("李四", 5000, 22);
//        mEmployee.setAddress("广东");
//        getFields(mEmployee);
//        getField(mEmployee, "mName");
//        setFieldValue(mEmployee, "mName", "张三");

//        getAnnotationMethod(mEmployee);

        classInstance();

    }

    // 调用了无参构造函数
    private Object createEmployeeByClassPath(String classPath){
        try {
            Class cl = Class.forName(classPath);
            Constructor constructor = cl.getConstructor();
            Object object = constructor.newInstance();
            Employee employee = (Employee) object;
            Log.i(TAG, "createEmployeeByClassPath " + employee.toString());
            return object;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Error" + e.getMessage());
        }
        return null;

        // 获取 private 的构造函数
//        Class cl = Class.forName(classPath);
//        Constructor constructor = cl.getDeclaredConstructor();
//        constructor.setAccessible(true);
//        Object object = constructor.newInstance();
    }

    // 调用有参构造函数
    private void createEmployeeByConstructor(String classPath, Class[] intArgsClass, Object[] intArgs){
        try {
            Class classType = Class.forName(classPath);
            Constructor constructor = classType.getConstructor(intArgsClass);
            constructor.setAccessible(true);  // 压制 java 检查,防止当构造函数时 private 时拿不到
            Object object = constructor.newInstance(intArgs);
            Employee employee = (Employee) object;

            Log.i(TAG, "createEmployeeByConstructor " + employee.toString());
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "createEmployeeByConstructor error " + e.getMessage());
        }
    }

    private void getMethods(Object object){
        // 获取所有方法,包括父类的
        Method[] methods = object.getClass().getMethods();
        for (Method method : methods){
            Log.i(TAG, "getMethods method " + method.toString());
        }

        Log.i(TAG, " ----------------------------------------");
        // 至获取自身定义的方法
        Method[] methods1 = object.getClass().getDeclaredMethods();
        for (Method method : methods1){
            Log.i(TAG, "getMethods method " + method.toString());
        }

    }

    // 反射调用方法
    private void invokeMethod(Object object, String methodName, Class[] intArgsClass, Object[] intArgs){
        try {
            Class clazz =  object.getClass();
            Method method = clazz.getDeclaredMethod(methodName, intArgsClass);
            method.setAccessible(true);
            Object returnValue = method.invoke(object, intArgs);
            Log.i(TAG, "invokeMethod returnValue ");
            print(object);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "invokeMethod error " + e.getMessage());
        }
    }

    // 获取成员变量
    private void getFields(Object object){
        Field[] fields = object.getClass().getFields();
        for (Field field : fields){
            Class type = field.getType();
            String name = field.getName();
            Log.i(TAG, " getFields type= " + type + "  name= " + name);
        }

        Log.i(TAG, " ----------------------------------------");

        // 获取方法的标识符
        Field[] fields1 = object.getClass().getDeclaredFields();
        for (Field field : fields1){
            Class type = field.getType();
            String name = field.getName();
            Log.i(TAG, " getFields type= " + type + "  name= " + name);
            printModifier(name, field.getModifiers());
        }
    }

    // 获取具体的成员变量
    private void getField(Object object, String fieldName){
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            Object fieldVale = field.get(object);
            String name = (String) fieldVale;
            Log.i(TAG, " getField name= " + name);
        } catch (Exception e) {
            e.printStackTrace();
            Log.i(TAG, " getField error= " + e.getMessage());
        }
    }

    // 设置成员变量的值
    private void setFieldValue(Object object, String fieldName, Object value){
        Log.i(TAG, "before set field ");
        print(object);
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(object, value);

            Log.i(TAG, "after set field ---- ");
            print(object);
        } catch (Exception e){
            e.printStackTrace();
            Log.i(TAG, " getField error= " + e.getMessage());
        }
    }

    // 获取注解的
    private void getAnnotationMethod(Object object){
        Method[] methods = object.getClass().getDeclaredMethods();
        for (Method method: methods){
            MyAnnotation annoType = method.getAnnotation(MyAnnotation.class);
            if (annoType != null){
                Log.i(TAG, "getAnnotationMethod name = " + method.getName());
            }
        }
    }


    private void print(Object object){
        Employee employee = (Employee) object;
        Log.i(TAG, "print " + employee.toString());
    }

    private void printModifier(String name, int modifier){
        String modifiers = Modifier.toString(modifier);

        boolean isFinal = Modifier.isFinal(modifier);
        Log.i(TAG, "name = " + name + " modifier= " + modifiers + " isFinal= " + isFinal);
    }

    // 不是用反射
    private void classInstance(){
        try {
            Employee employee  =  Employee.class.newInstance();
            Log.i(TAG, "classInstance " + employee.toString());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}

Employee.java

/**
 * Created by yxhuang
 * Date: 2018/11/10
 * Description:
 */
public class Employee extends Person {
    private static final String TAG = "Employee";

    private String mName;
    private long mSalary;

    public String mAddress;


    public Employee(){
        super(20);
        Log.i(TAG, "调用 Employee 无参构造函数");
    }

    public Employee(String name, long salary, int age) {
        super(age);
        mName = name;
        mSalary = salary;
        Log.i(TAG, "调用 Employee 有参参构造函数 name= " + name + " salary= " + salary);
    }


    public String getName() {
        return mName;
    }

    @MyAnnotation
    public void setName(String name) {
        Log.i(TAG, "set name " + name);
        mName = name;
    }

    public long getSalary() {
        return mSalary;
    }

    @MyAnnotation
    public void setSalary(long salary) {
        mSalary = salary;
    }

    public String getAddress() {
        return mAddress;
    }

    public void setAddress(String address) {
        mAddress = address;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "mName='" + mName + '\'' +
                ", mSalary=" + mSalary +
                ", mAag=" + mAag +
                '}';
    }
}

Person.java

public class Person {
    public int mAag;
    public Person(int aag) {
        mAag = aag;
    }
}

MyAnnotation.java

扫描二维码关注公众号,回复: 9346444 查看本文章
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyAnnotation {

}
发布了58 篇原创文章 · 获赞 20 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/yxhuang2008/article/details/84450529