likes
comments
collection
share

Android Coder带你了解反射

作者站长头像
站长
· 阅读数 48

前言

一般情况下,在使用某个类时必定清楚是什么类,作用是什么。使用时就直接对类进行实例化,调用对象进行操作。但在部分场景下开发时,开始并不知道操作类具体是什么,在运行时才知道具体类,并需要调用其方法,这就要使用反射来获取目标类的构造器,创建对应类对象,调用对应方法。

本篇就来说说反射知识。

概览

Android Coder带你了解反射

Class类

Class封装了当前对象所对应的类信息,每一个普通类都可以看成一个对象,是 java.lang.Class 类的对象,Class是描述类的类(有点拗口)

获取Class对象

有3种获取Class对象的方式:

  • 通过类名获取=> 类名.class
  • 通过对象名获取=> 对象名.getClass()
  • 通过全类名获取=> Class.forName(全类名) //类全名:加上包名路径 如:com.any.bean.User
User  user = new User();  // 正常 new关键字创建
Class userClass = User.class;     // 类名.class
User  userClass1 = user.getClass(); // 对象名.getClass()
Class userClass2 = Class.forName("com.any.bean.User");

创建实例

反射方式生成对象的实例:

Class userClass = User.class;  // 获取到目标类
User user = (User) userClass.newInstance(); // 获取到实例

获取构造器

获取构造器的方式:

  • Constructor getConstructor(Class[] params)获得使用指定参数类型的public构造函数
  • Constructor[] getConstructors():获得类所有公共构造函数
  • Constructor getDeclaredConstructor(Class[] params):获得使用特定参数类型的构造函数(包括私有)
  • Constructor[] getDeclaredConstructors():获得类的所有构造函数

新建一个 Person类,有私有属性和方法:

public class Person {

    public String name;
    private int age;

    ... // 省略掉 getter/setter

    public Person() {  // 无参公有构造器
        super();
    }
    
    public Person(String name, int age) { //
        this.name = name;
        this.age = age;
    }

    private void privateMethod(){
        System.out.println("the private method!");
    }
}

新建GetConstructor类来获取构造器:

public class GetConstructor {
    public static void main(String[] args) throws Exception{
        String className = "com.any.bean.Person";
        Class<Person> personClass = (Class<Person>) Class.forName(className);
        //获取全部公有constructor
        Constructor<?>[] constructors = personClass.getConstructors();
        for (Constructor<?> constructor: constructors) {
            System.out.println("获取到公有constructor: " + constructor);
        }
        //获取指定constructor
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        System.out.println("获取指定参数类型的constructor: " + constructor);

        //调用构造器 newInstance() 方法创建对象
        Person person = constructor.newInstance("Any", 27);
        System.out.println(person.getName() + ", " + person.getAge() );
    }
}

输出结果:

获取到公有constructor: public com.any.bean.Person(java.lang.String, int)
获取到公有constructor: public com.any.bean.Person()
获取指定参数类型的constructor: public com.any.bean.Person(java.lang.String, int)
any, 27

获取方法

获取方法有如下方式:

  • Method getMethod(String name, Class[] params):使用特定的参数类型,获得命名的公共方法
  • Method[] getMethods():获取类所有公共方法
  • Method getDeclaredMethod(String name, Class[] params):通过指定参数类型,获取类声明方法
  • Method[] getDeclaredMethods():获得类声明方法

GetMethod获取和调用方法:

public class GetMethod {
    public static void main(String[] args) throws Exception{
        Class<?> aClass = Class.forName("com.any.bean.Person");
        //获取所有方法(不包含父类方法)
        methods = aClass.getDeclaredMethods();
        for (Method method: methods) {
            System.out.println("获取到方法: " + method.getName() + "()");
        }

        System.out.println(“===========================”);

        //获取指定的方法
        Method method = aClass.getDeclaredMethod("setAge", int.class);
        System.out.println("获取指定的方法:" + method);

        //调用方法
        Object instance = aClass.newInstance();
        method.invoke(instance, 66);

        //调用私有方法
        method = aClass.getDeclaredMethod("privateMethod");
        method.setAccessible(true); // 需要调用此方法且设置为 true
        method.invoke(instance);
    }
}

运行结果,如下:

获取到方法: getName()
获取到方法: setName()
获取到方法: setAge()
获取到方法: privateMethod()
获取到方法: getAge()
===========================
获取指定的方法:public void com.any.bean.Person.setAge(int)
set age: 66
the private method!

获取成员变量

获取成员变量的方式:

  • Field getField(String name):获取指定名称的公共字段
  • Field[] getFields():获取所有公共字段
  • Field getDeclaredField(String name)`:获取类声明命名字段
  • `Field[] getDeclaredFields():获取类声明所有字段

GetField 获取成员变量:

public class GetField {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("com.any.bean.Person");
        // 获取所有字段(不包含父类字段)
        Field[] fields = aClass.getDeclaredFields();
        for (Field field: fields) {
            System.out.println("获取的字段: " + field.getName());
        }

        System.out.println(“================”);

        // 获取指定字段
        Field name = aClass.getDeclaredField(“name”);
        System.out.println("获取指定的字段: " + name.getName());

        // 设置指定字段的值
        Object instance = aClass.newInstance();
        name.set(instance, "Any");

        // 获取指定字段的值
        Object o = name.get(instance);
        System.out.println("获取指定字段的值: " + o);
    }
}

运行结果:

获取的字段: name
获取的字段: age
================
获取指定的字段: name
获取指定字段的值: Any

总结

Java 反射机制主要提供:

  • 运行时构造一个类的对象
  • 运行时获取任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法(属性)
转载自:https://juejin.cn/post/7151389797993414693
评论
请登录