写点什么

Android Coder 带你了解反射

作者:子不语Any
  • 2022 年 10 月 06 日
    湖南
  • 本文字数:2742 字

    阅读完需:约 9 分钟

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;     // 类名.classUser  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: 66the 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 反射机制主要提供:


  • 运行时构造一个类的对象

  • 运行时获取任意一个类所具有的成员变量和方法

  • 在运行时调用任意一个对象的方法(属性)

发布于: 刚刚阅读数: 2
用户头像

子不语Any

关注

还未添加个人签名 2022.09.17 加入

还未添加个人简介

评论

发布
暂无评论
Android Coder带你了解反射_后端_子不语Any_InfoQ写作社区