• android反射详解


    1,反射的定义

    一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的,并且能够获得此类的引用。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。

    反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。这时候,我们使用 JDK 提供的反射 API 进行反射调用。反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。是Java被视为动态语言的关键。

    Java反射机制主要提供了以下功能:

    ①在运行时构造任意一个类的对象

    ②在运行时获取或者修改任意一个类所具有的成员变量和方法

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

    2,Class

    反射始于Class,Class是一个类,封装了当前对象所对应的类的信息。

    一个类中有属性,方法,构造器等,比如说 有一个Person类,一个Order类,一个Book类,这些都是不同的类,现在需要一个类,用来描述类,这就是 Class,它应该有类名,属性,方法,构造器等。Class是用来描述类的类。

    Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等。对于每 个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。 对象只 能由系统建立对象,一个类(而不是一个对象)在 JVM 中只会有一个Class实例

    2.1获取Class对象

    获取Class对象的三种方式

    ①. 通过类名获取 类名.class

    ②. 通过对象获取 对象名.getClass()

    ③. 通过全类名获取 Class.forName(全类名) classLoader.loadClass(全类名)

    例如获取People的Class对象:

    1. public class People {
    2. private String name;
    3. private int age;
    4. public void setName(String name) {
    5. this.name = name;
    6. }
    7. public void setAge(int age) {
    8. this.age = age;
    9. }
    10. public String getName() {
    11. return name;
    12. }
    13. public int getAge() {
    14. return age;
    15. }
    16. }

    通过三种方式获取: 

    1. //方式一 通过类名获取 类名.class
    2. Class peopleClass = People.class;
    3. //方式二 通过对象获取 对象名.getClass()
    4. People people =new People();
    5. Classextends People> peopleClass1 = people.getClass();
    6. //方式三 通过全类名获取 Class.forName(全类名) classLoader.loadClass(全类名)
    7. try {
    8. Class peopleClass2 = Class.forName("com.yuanzhen.People");
    9. } catch (ClassNotFoundException e) {
    10. throw new RuntimeException(e);
    11. }

    方式一需要导入类的包,依赖太强,不导包就抛编译错误

    方式二一般可以创建对象就不需要反射了

    方式三最常用,没有依赖性

    2.2判断是否为某个类的实例

    1. //peopleClass 是否为People.class的实例
    2. boolean assignableFrom = peopleClass.isAssignableFrom(People.class);

    2.3创建实例

    通过反射来生成对象主要有两种方式:

    ①使用Class对象的newInstance()方法来创建Class对象对应类的实例。

    ②先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这 种方法可以用指定的构造器构造类的实例。

    例如:

    1. //方式一 使用Class对象的newInstance()方法来创建Class对象对应类的实例
    2. try {
    3. People people1 = peopleClass.newInstance();
    4. } catch (IllegalAccessException e) {
    5. throw new RuntimeException(e);
    6. } catch (InstantiationException e) {
    7. throw new RuntimeException(e);
    8. }
    1. //方式二 先通过Class对象获取指定的Constructor对象
    2. //再调用Constructor对象的newInstance()方法来创建实例
    3. //这种方法可以用指定的构造器构造类的实例
    4. Constructor constructor = null;
    5. try {
    6. constructor = peopleClass.getConstructor(People.class);
    7. constructor.newInstance();
    8. } catch (Exception e) {
    9. throw new RuntimeException(e);
    10. }

    3,构造器

    上面提到了通过构造器可以创建对象,那么怎么获得构造器呢?

    获得构造器的api:

    Constructor getConstructor(Class[] params)获得使用特殊的参数类型的public构造函数(包括父类)
    Constructor[] getConstructors()获得类的所有公共构造函数
    Constructor getDeclaredConstructor(Class[] params)获得使用特定参数类型的构造函数(包括私有)
    Constructor[] getDeclaredConstructors()获得类的所有构造函数(与接入级别无关)

    例如:

    1. public class People {
    2. public People(String name, int age) {
    3. this.name = name;
    4. this.age = age;
    5. }
    6. private People() {
    7. }
    8. public People(String name) {
    9. this.name = name;
    10. }
    11. }
    1. try {
    2. //获取Class对象
    3. Class peopleClass = Class.forName("com.yuanzhen.People");
    4. //获得使用特殊的参数类型的public构造函数(包括父类)
    5. Constructor constructor = peopleClass.getConstructor(String.class, int.class);
    6. //获得使用特定参数类型的构造函数(包括私有)
    7. constructor = peopleClass.getDeclaredConstructor();
    8. //获得类的所有公共构造函数
    9. Constructor[] constructors = peopleClass.getConstructors();
    10. //获得类的所有构造函数(与接入级别无关)
    11. constructors = peopleClass.getDeclaredConstructors();
    12. } catch (Exception e) {
    13. throw new RuntimeException(e);
    14. }

    4,成员变量

    4.1获取成员变量

    获取类的成员变量的api:

    Field getField(String name)获得命名的公共字段
    Field[] getFields()获得类的所有公共字段
    Field getDeclaredField(String name)获得类声明的命名的字段
    Field[] getDeclaredFields()获得类声明的所有字段

    例如:

    1. public class People {
    2. public String name;
    3. private int age;
    4. public void setName(String name) {
    5. this.name = name;
    6. }
    7. public void setAge(int age) {
    8. this.age = age;
    9. }
    10. public String getName() {
    11. return name;
    12. }
    13. public int getAge() {
    14. return age;
    15. }
    16. }
    1. try {
    2. //获取Class对象
    3. Class peopleClass = Class.forName("com.yuanzhen.People");
    4. //获得命名的公共字段 name
    5. Field field = peopleClass.getField("name");
    6. //获得类声明的命名的字段(包括私有) age
    7. Field field1 = peopleClass.getDeclaredField("age");
    8. //获得类的所有公共字段
    9. Field[] fields = peopleClass.getFields();
    10. //获得类声明的所有字段
    11. Field[] fields1 = peopleClass.getDeclaredFields();
    12. } catch (Exception e) {
    13. throw new RuntimeException(e);
    14. }

    4.2调用成员变量

    将成员变量赋值:

    1. try {
    2. //获取Class对象
    3. Class peopleClass = Class.forName("com.yuanzhen.People");
    4. //获得命名的公共字段 name
    5. Field field = peopleClass.getField("name");
    6. //获得类声明的命名的字段(包括私有) age
    7. Field field1 = peopleClass.getDeclaredField("age");
    8. //创建对象
    9. Object people = peopleClass.newInstance();
    10. //暴力反射,解除私有限定
    11. field1.setAccessible(true);
    12. //将年龄设为20
    13. field1.set(people,20);
    14. //将姓名设为张三
    15. field.set(people,"张三");
    16. } catch (Exception e) {
    17. throw new RuntimeException(e);
    18. }

    5,成员方法

    5.1获取成员方法

    获取方法信息的api:

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

    例如:

    1. public class People {
    2. public String name;
    3. private int age;
    4. private void setName(String name) {
    5. this.name = name;
    6. }
    7. public void setAge(int age) {
    8. this.age = age;
    9. }
    10. private String getName() {
    11. return name;
    12. }
    13. public int getAge() {
    14. return age;
    15. }
    16. }
    1. try {
    2. //获取Class对象
    3. Class peopleClass = Class.forName("com.yuanzhen.People");
    4. //使用特定的参数类型,获得命名的公共方法
    5. Method method = peopleClass.getMethod("setAge", int.class);
    6. //使用特写的参数类型,获得类声明的命名的方法(包括私有)
    7. Method method1 = peopleClass.getDeclaredMethod("setName", String.class);
    8. //获得类的所有公共方法
    9. Method[] methods = peopleClass.getMethods();
    10. //获得类声明的所有方法(包括私有)
    11. Method[] methods1 = peopleClass.getDeclaredMethods();
    12. } catch (Exception e) {
    13. throw new RuntimeException(e);
    14. }

    5.2调用成员方法

    1. try {
    2. //获取Class对象
    3. Class peopleClass = Class.forName("com.yuanzhen.People");
    4. //使用特定的参数类型,获得命名的公共方法
    5. Method method = peopleClass.getMethod("setAge", int.class);
    6. //使用特写的参数类型,获得类声明的命名的方法(包括私有)
    7. Method method1 = peopleClass.getDeclaredMethod("setName", String.class);
    8. //创建对象实例
    9. Object people = peopleClass.newInstance();
    10. //暴力反射,解除私有限定
    11. method.setAccessible(true);
    12. //调用方法setAge
    13. method.invoke(people,20);
    14. //调用方法 setName
    15. method1.invoke(people,"张三");
    16. } catch (Exception e) {
    17. throw new RuntimeException(e);
    18. }

    6,总结

    反射的常规使用就是这些,本文主要是对常用反射api的记录总结。

  • 相关阅读:
    SocketLog 的基本使用
    element-ui组件table去除下方滚动条,实现鼠标左右拖拽移动表格
    一篇文章教你学会ASP.Net Core LINQ基本操作
    【考研英语词汇训练营】Day 16 —— bankrupt,remain,regulate,construct,reflect
    函数式接口
    vivo统一接入网关VUA转发性能优化实践
    Maven环境搭建
    vue 语法
    STM32的光敏检测自动智能窗帘控制系统proteus设计
    C++的运算符重载介绍
  • 原文地址:https://blog.csdn.net/y2653904/article/details/132795200