android反射详解

news/2024/5/19 6:03:39 标签: android, java, 反射

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对象:

java">public class People {

    private String name;

    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

通过三种方式获取: 

java">//方式一 通过类名获取 类名.class
Class<People> peopleClass = People.class;

//方式二 通过对象获取 对象名.getClass()
People people =new People();
Class<? extends People> peopleClass1 = people.getClass();

//方式三 通过全类名获取 Class.forName(全类名) classLoader.loadClass(全类名)
try {
    Class<?> peopleClass2 = Class.forName("com.yuanzhen.People");
} catch (ClassNotFoundException e) {
    throw new RuntimeException(e);
}

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

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

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

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

java">//peopleClass 是否为People.class的实例
boolean assignableFrom = peopleClass.isAssignableFrom(People.class);

2.3创建实例

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

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

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

例如:

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

3,构造器

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

获得构造器的api:

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

例如:

java">public class People {

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }
    private People() {

    }
    public People(String name) {
        this.name = name;
    }
}
java">try {
    //获取Class对象
    Class<?> peopleClass = Class.forName("com.yuanzhen.People");
    //获得使用特殊的参数类型的public构造函数(包括父类)
    Constructor<?> constructor = peopleClass.getConstructor(String.class, int.class);
    //获得使用特定参数类型的构造函数(包括私有)
   constructor = peopleClass.getDeclaredConstructor();
   //获得类的所有公共构造函数
    Constructor<?>[] constructors = peopleClass.getConstructors();
    //获得类的所有构造函数(与接入级别无关)
    constructors = peopleClass.getDeclaredConstructors();
} catch (Exception e) {
    throw new RuntimeException(e);
}

4,成员变量

4.1获取成员变量

获取类的成员变量的api:

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

例如:

java">public class People {

    public String name;

    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
java">try {
    //获取Class对象
    Class<?> peopleClass = Class.forName("com.yuanzhen.People");
    //获得命名的公共字段  name
    Field field = peopleClass.getField("name");
    //获得类声明的命名的字段(包括私有) age
    Field field1 = peopleClass.getDeclaredField("age");
    //获得类的所有公共字段
    Field[] fields = peopleClass.getFields();
    //获得类声明的所有字段
    Field[] fields1 = peopleClass.getDeclaredFields();
} catch (Exception e) {
    throw new RuntimeException(e);
}

4.2调用成员变量

将成员变量赋值:

java">try {
    //获取Class对象
    Class<?> peopleClass = Class.forName("com.yuanzhen.People");
    //获得命名的公共字段  name
    Field field = peopleClass.getField("name");
    //获得类声明的命名的字段(包括私有) age
    Field field1 = peopleClass.getDeclaredField("age");
    //创建对象
    Object people = peopleClass.newInstance();
    //暴力反射,解除私有限定
    field1.setAccessible(true);
    //将年龄设为20
    field1.set(people,20);
    //将姓名设为张三
    field.set(people,"张三");
} catch (Exception e) {
    throw new RuntimeException(e);
}

5,成员方法

5.1获取成员方法

获取方法信息的api:

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

例如:

java">public class People {

    public String name;

    private int age;

    private void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
java">try {
    //获取Class对象
    Class<?> peopleClass = Class.forName("com.yuanzhen.People");
    //使用特定的参数类型,获得命名的公共方法
    Method method = peopleClass.getMethod("setAge", int.class);
    //使用特写的参数类型,获得类声明的命名的方法(包括私有)
    Method method1 = peopleClass.getDeclaredMethod("setName", String.class);
    //获得类的所有公共方法
    Method[] methods = peopleClass.getMethods();
    //获得类声明的所有方法(包括私有)
    Method[] methods1 = peopleClass.getDeclaredMethods();
    
} catch (Exception e) {
    throw new RuntimeException(e);
}

5.2调用成员方法

java">try {
    //获取Class对象
    Class<?> peopleClass = Class.forName("com.yuanzhen.People");
    //使用特定的参数类型,获得命名的公共方法
    Method method = peopleClass.getMethod("setAge", int.class);
    //使用特写的参数类型,获得类声明的命名的方法(包括私有)
    Method method1 = peopleClass.getDeclaredMethod("setName", String.class);
    //创建对象实例
    Object people = peopleClass.newInstance();
    //暴力反射,解除私有限定
    method.setAccessible(true);
    //调用方法setAge
    method.invoke(people,20);
    //调用方法 setName
    method1.invoke(people,"张三");
} catch (Exception e) {
    throw new RuntimeException(e);
}

6,总结

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


http://www.niftyadmin.cn/n/5017015.html

相关文章

php的html实体和字符之间的转换

html_entity_decode() 函数是 htmlentities() 函数的反函数。用于把HTML实体转换为字符。 html_entity_decode() 函数把 HTML 实体转换为字符。 $str "<© W3CS&ccedil;h&deg;&deg;&brvbar;&sect;>"; echo html_entity_decode($str…

【LeetCode第362场周赛】8020.字符串转换 | 推导+矩阵快速幂+KMP | 困难

题目内容 原题链接 给定两个长度均为 n n n 的字符串 s s s 和 t t t 。 每次选择一个长度为 l ( 0 < l < n ) l(0<l<n) l(0<l<n) 的 s s s 的后缀字符串 s u f suf suf&#xff0c;将 s u i f suif suif 从 s s s 中删除&#xff0c;并添加到 s s…

[js] 图解 event.pageX event.clientX event.offsetX getBoundingClientRect

event.clientX、event.clientY 鼠标相对于浏览器窗口可视区域的X&#xff0c;Y坐标&#xff08;窗口坐标&#xff09;&#xff0c;可视区域不包括工具栏和滚动条。IE事件和标准事件都定义了这2个属性 event.pageX、event.pageY 类似于event.clientX、event.clientY&#xff0c;…

webgl与webgpu比较

绘制流程 webgl无论是操作着色器&#xff0c;还是操作 VBO&#xff0c;亦或者是创建一些 Buffer、Texture 对象&#xff0c;基本上都得通过 gl 变量一条一条函数地走过程&#xff0c;顺序是非常讲究的。每一次调用 gl.xxx 时&#xff0c;都会完成 CPU 到 GPU 的信号传递&#…

【数据结构】AVL树的插入与验证

文章目录 一、基本概念1.发展背景2.性质 二、实现原理①插入操作1.平衡因子1.1平衡因子的更新1.1.1树的高度变化1.1.2树的高度不变 2. 旋转2.1左旋2.2右旋2.3右左双旋2.4 左右双旋 ②验证1.求二叉树高度2. 判断是否为AVL树 源码总结 一、基本概念 1.发展背景 普通的二叉搜索树…

融合康养产业、乐享宜居灞桥,西安市灞桥康养论坛即将举办

随着我国人口老龄化进程的不断加速以及人们的健康意识不断提高&#xff0c;我国康养产业逐步发展壮大。9月15日&#xff0c;以“融合康养产业、乐享宜居灞桥”为主题的灞桥康养论坛将在西安市灞桥区盛大召开。 据悉&#xff0c;此次论坛由西安市人民政府、陕西省民政厅主办&am…

博客之QQ登录功能(一)

流程图 上图spring social 封装了1-8步需要的工作 1、新建包和书写配置文件 public class QQProperties {//App唯一标 识private String appId "100550231";private String appSecret "69b6ab57b22f3c2fe6a6149274e3295e";//QQ供应商private String…

Pandas 掉包侠刷题实战--条件筛选

本博文内容为力扣刷题过程的记录&#xff0c;所有题目来源于力扣。 题目链接&#xff1a;https://leetcode.cn/studyplan/30-days-of-pandas/ 文章目录 准备工作1. isin(values) 和 ~2. df.drop_duplicates()3. df.sort_values()4. df.rename()5. pd.merge() 题目-条件筛选1. 大…