Java 反射使用大全

news/2024/5/19 6:59:22 标签: java, android, javaEE, 反射, reflect

前言

好多年前自己记的关于Java反射的笔记,这么些年下来,自己用到反射的时候就看这一份就够了。
但是笔记以文件形式存放不方便,所以将其放到CSDN中,也希望能给更多小伙伴带来帮助。

Class类

Java程序中的各个Java类属于同一种事物,描述这类事物的Java类名就是Class

人 -> Person
Java类 -> Class

获取各个字节码对应的实例对象

方法一 : 类名:class

java">Class cls1 = Person.class;

方法二 : 对象:getClass

java">Class cls2 = p1.getClass();

方法三 : forName

java">Class cls3 = Class.forName("java.lang.String");

方法四 : getClassLoader().getClass

java"> Class clazz = getClassLoader().getClass("java.lang.String");

.class()、getClass()、Class.forName()、getClassLoader()的区别

.class是获取声明时的类。
getClass()是获取运行时的类。
Class.forName()是通过类名来获得类。
getClassLoader()是获得类的加载器。

若字节码曾经被加载过,已经待在Java虚拟机里面了,可以直接返回,如方法一和方法二
Java虚拟机中还没有这份字节码,则用类加载器去加载,把加载的字节码缓存到虚拟机中,以后,使用这份字节码就不需要加载了,如方法三

预定义对象

9个预定义对象,8个基本类型和void

java">Class class1 = boolean.class;
Class class2 = int.class;
//.......
Class class3 = Void.class;

isPrimitive判断是否是基本类型

java">int.class.isPrimitive

isArray判断是否是数组

java">int[].class.isArray

获得类型

java">getclass().getName();

反射

反射就是把Java类中的各种成分映射成相应的Java

Field:成员变量
Method:方法
Constructor:构造方法
Package:包

Constructor

得到某个类所有的构造方法

java">Class.forName("java.lang.String").getConstructors();

得到某一个构造方法

根据getConstructor中的参数返回相应的构造方法

java">Class.forName("java.lang.String").getConstructor(StringBuffer.class);

Constructor可以干什么

获取实例对象(一个constructor可以new出很无数个实例对象)

java">(强制转换)constructor1.newInstance(参数要和getConstructor中的一致);

通过默认构造方法创建实例(内部会缓存实例,第二次获取就不会再创建,直接获取)

java">String obj = (String) Class.frName("java.lang.String").newInstance();

原版反射的步骤是 Class -> Constructor -> newInstanceClass.newInstance()直接在内部Constructor,即直接Class -> Class.newInstance()即可获得默认构造方法的实例

Field

代表某个类中的一个成员变量

Person类

java">public class Person {
    public String name;

    private int age;

    public int getAge() {
        return age;
    }

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

通过反射获取成员变量

java">Person person = new Person();
person.setAge(20);
person.name = "Heiko";
//Field fieldName = person.getClass().getField("name"); 都可以
Field fieldName = Class.forName("reflectTest.Person").getField("name");
//fieldName的值为多少?不是Heiko,因为fieldName不是对象身上的变量,而是类上,要通过field.get("实例")或getDeclaredField来获取该实例上的值
String name = (String) fieldName.get(person);
System.out.println("name:" + name);

//对于私有变量,需暴力破解
Field fieldAge = person.getClass().getDeclaredField("age"); //getDeclaredField 不管是私有还是public的,都可以获取
fieldAge.setAccessible(true); //设置可以访问 fieldAge.get("age")
int age = (int) fieldAge.get(person);
System.out.println("age:" + age);  

获取静态变量

java">Field filed = obj.getClass().getField(cmdFieldName);
Integer cmdValue = (Integer) filed.get(null); //获取静态变量

获得所有的成员变量

java">obj.getClass().getFields();

getFields和getDeclaredFields的区别

getFields() : 只能访问类中声明为公有的字段,私有的字段它无法访问,能访问从其它类继承来的公有方法
getDeclaredFields() : 能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的方法

比较成员变量类型

java">if(field.getType() == String.class)

设置值

java">field.set(obj,新的值);

将实例中的String类型的成员变量值的b都换成a

java">//将对象中的String类型的成员变量所有的字符b换为字符a
private static void exchangeCharValue(Object obj) throws Exception {
    Field[] fields = obj.getClass().getFields();
    for(Field field : fields){
		//if(field.getType().equals(String.class)){ 
        if(field.getType() == String.class){ //这里用 == 比equals更准确,字节码只有一份自己和自己比较
            String oldValue = (String)field.get(obj);
            String newValue = oldValue.replace('b', 'a');
            field.set(obj, newValue);
        }
    }
}

Method

代表某个类中的一个成员方法

java">method.invoke(owner, args)
  • owner:执行这个方法的对象,args:参数,可以这么理解:owner对象中带有参数args的method方法。
  • 返回值是Object,也既是该方法的返回值。
java">String s = "abc";  
Method methodCharAt = String.class.getMethod("charAt", int.class);
String newString =methodCharAt.invoke(s, 1);//invoke是方法身上的方法,s是执行该方法的对象(必须是实例化的对象)
System.out.println(newString); 

调用静态方法

java">methodCharAt.invoke(null,);

反射数组

  • 若数组的维数(一维、二维等)和数组类型都相等,那么他们的字节码是同一个
  • 代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
  • 基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用
  • 非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用

ArrayList.asList时int[]和String[]的差别

因为asList接收Object[]类型,但int[]不是Object[]类型,所以交给jdk1.5之后的asList(T...t)处理,将int[]作为一个对象处理

java">Arrays.asList(new int[]{1,2,3}); //打印内容为:[@hascode]
Arrays.asList(new String[]{"1","2","3"}); //打印内容为:[1,2,3]

数组的反射应用

输出数组

java">private static void printObject(Object obj) {
    Class clazz = obj.getClass();
    if (clazz.isArray()) { //如果是数组
        int len = Array.getLength(obj);
        for (int i = 0; i < len; i++) {
            System.out.println(Array.get(obj, i));
        }
    } else {
        System.out.println(obj);
    }
}  

调用

java">String[] array = new String[] { "1", "2", "3" };
String valueString = "test";
printObject(array);
printObject(valueString);

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

相关文章

卡尔曼滤波与组合导航原理(十二)扩展卡尔曼滤波:EKF、二阶EKF、迭代EKF

文章目录 一、多元向量的泰勒级数展开二、扩展Kalman滤波三、二阶滤波四、迭代EKF滤波 一、多元向量的泰勒级数展开 { y 1 f 1 ( X ) f 1 ( x 1 , x 2 , ⋯ x n ) y 2 f 2 ( X ) f 2 ( x 1 , x 2 , ⋯ x n ) ⋮ y m f m ( X ) f m ( x 1 , x 2 , ⋯ x n ) \left\{\begin{…

ASP.NET Core Web API入门之一:创建新项目

ASP.NET Core Web API入门之一&#xff1a;创建新项目 一、引言二、创建新项目三、加入Startup类&#xff0c;并替换Program.cs内容四、编辑Program.cs代码五、修改控制器的路由六、运行项目 一、引言 最近闲着&#xff0c;想着没真正从0-1开发过ASP.NET Core Web API的项目&a…

如何设计一个完整的交互流程,提升产品用户体验

交互流程设计是一项关乎用户体验的重要工作。通过设计和规划用户与产品或服务的交互方式和流程&#xff0c;我们可以提高用户的满意度和使用效果。在本文中&#xff0c;我们将深入探讨交互流程设计的关键要素以及其对用户体验的重要性。 交互流程设计本质是通过设计和规划用户与…

Get请求如何传递数组、对象

文章目录 Get请求如何传递数组1、将数组参数传递多次2、直接将数组指用逗号分隔 Get请求如何传递对象 Get请求如何传递数组 1、将数组参数传递多次 可以将数组参数传递多次&#xff0c;springmvc会将多个同名参数自动封装成数组或者集合对象&#xff0c;示例如下&#xff1a;…

关系数据模型

1.键的概念 超键&#xff1a;在一个关系中&#xff0c;能唯一标识元组的属性或属性集&#xff08;可能存在多余的属性&#xff09; 侯选建&#xff1a;如果一个属性集能唯一标识元组&#xff08;超键&#xff09;&#xff0c;且又不含有多余的属性&#xff0c;那么这个属性集…

C++ std::thread 与Qt qthread多线程混合编程

C与Qt深度融合&#xff1a;高效设计多线程应用框架 1. C与Qt线程的混合使用1.1 C线程与Qt线程的基本概念1.2 线程间的相互依赖关系1.3 设计合理的代码框架 二、深入理解C和Qt线程模型2.1 C线程模型2.2 Qt线程模型2.3 C和Qt线程模型的比较 三、C和Qt线程间的互操作性3.1 std::th…

路径规划算法:基于和声优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于和声优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于和声优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法和声…

JAVA要点复习

标识符数据类型 变量类型 数据类型的存储空间 自动转换 强制转换 错误类型 习题 2.9 P22-3 方法 方法定义 方法头标识&#xff08;定义&#xff09; 一般格式 访问修饰符 方法调用 参数传递&#xff08;基本类型&#xff0c;引用传参&#xff09; 方法重载 计算阶乘&#xff0…