当前位置: 首页 > news >正文

Java反射:打破静态限制的利器

目录

什么是反射?

什么是class类?

获取class对象的三种方法

利用反射获取构造方法

利用反射获取成员变量

利用反射获取成员方法

案例1

案例2

反射的作用

什么是反射?

反射允许对封装累的字段(成员变量),方法(成员方法)和构造函数(构造方法)的信息进行编程访问。

反射就是从类里面拿东西

反射允许对成员变量,成员方法和构造方法的信息进行编程访问。

但我们在获取的时候并不是从Java文件中获取的,而是从class字节码文件中获取的,所以我们要先创建class字节码文件对象,再从字节码文件里面获取字段,构造方法,成员方法。

什么是class类?

在Java编程语言中,Class类是一个非常特殊的类,它用于在运行时表示类或接口的信息。每当JVM加载一个类时,都会创建该类的一个Class对象,其中包含了类的名称、包名、父类、实现的接口、所有方法、字段等信息。这个Class对象是由JVM内部创建的,我们无法直接通过new来实例化一个Class对象。

Class类的主要作用是提供了一种在运行时获取类的各种信息的方法。

获取class对象的三种方法

  1. Class.forName("全类名");//源代码阶段
  2. 类名.class;//加载阶段
  3. 对象.getClass();//运行阶段
public class MyReflectDemo1 {public static void main(String[] args) throws ClassNotFoundException {//1.第一种方式//全类名:包名+类名//clazz表示Student类字节码文件的对象//最常用Class clazz1 = Class.forName("com.it.myreflect1.Student");System.out.println(clazz);//第二种方式//一般 更多的是当做参数进行传播Class clazz2 = Student.class;//第三种方式//当我们有了这个类的对象的 时候,才可以使用Student  stu = new Student();Class clazz3 = stu.getClass();}
}

运行结果:

表示的是:com.it.myreflect1.Student类的class对象

class类对象的唯一性

可以对三个结果进行比较,答案为true。

System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);

利用反射获取构造方法

在Java里面,万物皆可为对象,字节码文件可以看做是class对象,那么构造方法的对象用Constructor类的对象表示,成员变量的对象用File类的对象表示,成员方法的对象用Method类的对象表示。

class类中用于获取构造方法的方法

Constructor[] getConstructors();返回所有公共构造方法对象的数组

Constructor[] getDeclaredConstructors();返回所有构造方法对象的数组(Declared就相当于权限的意思,有了Declare就可以访问所有的构造方法)

Constructor getConstructor(Class…parameterTypes);返回单个公共构造方法对象

Constructor getDeclaredConstructor(Class……parameterTypes);返回单个构造方法对象

Constructor类中用于创建对象的方法

T newInstance(Object... initargs);根据指定的构造方法创建对象

setAccessible(boolean flag);设置为true,表示取消访问检查

//1.获取class字节码文件对象
Class clazz = Class.forName("com.it.myreflect2.Student");//2.获取构造方法
//返回所有公共构造方法对象的数组
System.out.println("----返回所有公共构造方法对象的数组----");
Constructor[] con1 = clazz.getConstructors();
for(Constructor c : con1){System.out.println(c);
}System.out.println("----返回所有构造方法对象的数组----");
Constructor[] con2 = clazz.getDeclaredConstructors();
for(Constructor c : con2) {System.out.println(c);
}
System.out.println("----返回单个构造方法对象(无参的构造方法)----");
Constructor cons1 = clazz.getDeclaredConstructor();
System.out.println(cons1);System.out.println("----返回单个构造方法对象(有参的构造方法)-----");
Constructor cons2 = clazz.getDeclaredConstructor(String.class);
System.out.println(cons2);System.out.println("----返回单个构造方法对象(受保护的)----");
Constructor con3 = clazz.getDeclaredConstructor(int.class);
System.out.println(con3);

运行结果

----返回所有公共构造方法对象的数组----
public com.it.myreflect2.Student()
public com.it.myreflect2.Student(java.lang.String)
----返回所有构造方法对象的数组----
public com.it.myreflect2.Student()
public com.it.myreflect2.Student(java.lang.String)
protected com.it.myreflect2.Student(int)
private com.it.myreflect2.Student(java.lang.String,int)
----返回单个构造方法对象(无参的构造方法)----
public com.it.myreflect2.Student()
----返回单个构造方法对象(有参的构造方法)-----
public com.it.myreflect2.Student(java.lang.String)
----返回单个构造方法对象(受保护的)----
protected com.it.myreflect2.Student(int)

获取权限修饰符

Constructor con4 = clazz.getDeclaredConstructor(String.class, int.class);
//获取权限修饰符
int modifiers = con4.getModifiers();
System.out.println(modifiers);//公有返回1,私有返回2

获取到构造方法的所有参数

Parameter[] parameters = con4.getParameters();
for(Parameter p : parameters){System.out.println(p);
}
//java.lang.String arg0
//int arg1

创建对象

con4.setAccessible(true);//表示临时取消权限校验
Student stu = (Student) con4.newInstance("张三", 23);//Object强转Student类型
System.out.println(stu);
//Student{name='张三', age=23}

利用反射获取成员变量

Class类中用于获取成员变量的方法

Field[]getFields(): 返回所有公共成员变量对象的数组

Field[]getDeclaredFields(): 返回所有成员变量对象的数组

Field getField(String name): 返回单个公共成员变量对象

Field getDeclaredField(String name): 返回单个成员变量对象

Field类中用于创建对象的方法

void set(Object obj, Object value): 赋值

Object get(Object obj)获取值。

public class MyReflectDemo {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {//先创建class对象Class clazz = Class.forName("com.it.myreflect6.Student");//获取成员变量Field[] name1 = clazz.getFields();for(Field f : name1) {System.out.println(f.getName());}System.out.println("----获取单个成员变量----");Field name2 = clazz.getDeclaredField("name");System.out.println(name2);System.out.println("----获取权限修饰符---");int modifiers = clazz.getModifiers();System.out.println(modifiers);System.out.println("---获取成员变量的名字---");String name = clazz.getName();System.out.println(name);System.out.println("---获取成员变量的类型---");String typeName = clazz.getTypeName();System.out.println(typeName);System.out.println("---获取成员变量记录的值---");Student s = new Student("张三",23);System.out.println(s);}
}

运行结果:

----获取单个成员变量----
private java.lang.String com.it.myreflect6.Student.name
----获取权限修饰符---
1
---获取成员变量的名字---
com.it.myreflect6.Student
---获取成员变量的类型---
com.it.myreflect6.Student
---获取成员变量记录的值---
Student{name='张三', age=23}

利用反射获取成员方法

Class类中用于获取成员方法的方法

Method[]getMethods(): 返回所有公共成员方法对象的数组,包括继承的

Method[]getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的

Method getMethod(String name, Class……parameterTypes): 返回单个公共成员方法对象

Method getDeclaredMethod(String name, Class…parameterTypes): 返回单个成员方法对象

Method类中用于创建对象的方法

Object invoke(Object obj, Object…args):

运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

//1.获取class字节码文件对象
Class clazz = Class.forName("com.it.myreflect3.Student");System.out.println("---包含继承父类的---");
Method[] methods1 = clazz.getMethods();
for (Method method : methods1) {System.out.println(method);
}System.out.println("---不包含继承父类的---");
Method[] methods2 = clazz.getDeclaredMethods();
for (Method method : methods2) {System.out.println(method);
}

运行结果

---包含继承父类的---
public java.lang.String com.it.myreflect3.Student.getName()
public java.lang.String com.it.myreflect3.Student.toString()
public void com.it.myreflect3.Student.sleep()
public void com.it.myreflect3.Student.setName(java.lang.String)
public int com.it.myreflect3.Student.getAge()
public void com.it.myreflect3.Student.setAge(int)
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public final void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
---不包含继承父类的---
public java.lang.String com.it.myreflect3.Student.getName()
public java.lang.String com.it.myreflect3.Student.toString()
public void com.it.myreflect3.Student.sleep()
public void com.it.myreflect3.Student.setName(java.lang.String)
public int com.it.myreflect3.Student.getAge()
public void com.it.myreflect3.Student.setAge(int)
private void com.it.myreflect3.Student.eat(java.lang.String) throws java.lang.NegativeArraySizeException,java.io.IOException

成员方法的运行

//获取指定的单一方法
Method m = clazz.getDeclaredMethod("eat",String.class);
System.out.println(m);
//获取方法的修饰符
int mod = m.getModifiers();
System.out.println(mod);
//获取方法的名字
String name = m.getName();
System.out.println(name);
//获取方法的形参
Parameter[] parameters = m.getParameters();
for(Parameter p : parameters){System.out.println(p);
}
//获取方法的抛出的异常
Class[] exceptionTypes = m.getExceptionTypes();
for(Class c : exceptionTypes){System.out.println(c);
}
//方法运行
Student s = new Student();
m.setAccessible(true);
Object result = m.invoke(s,"汉堡包");
System.out.println(result);

运行结果

---获取指定的单一方法---
private void com.it.myreflect3.Student.eat(java.lang.String) throws java.lang.NegativeArraySizeException,java.io.IOException
---获取方法的修饰符---
2
---获取方法的名字---
eat
---获取方法的形参---
java.lang.String arg0
---获取方法的抛出的异常---
class java.lang.NegativeArraySizeException
class java.io.IOException
---方法运行---
在吃汉堡包
null

案例1

对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去

public class MyReflectDemo {public static void main(String[] args) throws IllegalAccessException, IOException {/*对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去*///创建学生和老师的对象Student s = new Student("张三",23);Teacher t = new Teacher("波妞",34);getSaveObject(t);}private static void getSaveObject(Object obj) throws IllegalAccessException, IOException {//获取字节码对象Class clazz = obj.getClass();//创建IO流BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\java\\basic-code\\myreflect\\a.txt"));//获取所有的成员变量Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);//获取成员变量的名字String name = field.getName();//获取成员变量的值Object value = field.get(obj);bw.write(name+"="+value);bw.newLine();}bw.close();}
}

运行结果:a.txt文件有内容输入

name=波妞
age=34

案例2

配置文件中的信息为:

classname=com.it.myreflect5.Student

method=study

public class MyReflectDemo {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//1.读取配置文件中的信息Properties prop = new Properties();FileInputStream fis = new FileInputStream("D:\\java\\basic-code\\myreflect\\prop.properties");prop.load(fis);fis.close();System.out.println(prop.getProperty("name"));//2.获取全类名和方法名String className = (String) prop.get("classname");String methodName = (String) prop.get("method");System.out.println(className);System.out.println(methodName);//3.利用反射创建对象并运行方法Class clazz = Class.forName(className);//获取构造方法Constructor con = clazz.getDeclaredConstructor();Object o = con.newInstance();System.out.println(o);//获取成员方法并运行Method m = clazz.getDeclaredMethod(methodName);m.setAccessible(true);m.invoke(o);}
}

运行结果:

null
com.it.myreflect5.Student
study
Student{name='null', age=0}
学生在学习

反射的作用

  1. 获取任意一个类中的所有信息
  2. 结合配置文件动态创建对象
http://www.dtcms.com/a/288807.html

相关文章:

  • 【笔记】Anaconda 重装后虚拟环境写入路径异常的完整排查与解决过程
  • MySQL—表设计和聚合函数以及正则表达式
  • LeetCode 1712.将数组分成三个子数组的方案数
  • ZooKeeper学习专栏(二):深入 Watch 机制与会话管理
  • BST(二叉搜索树)的笔试大题(C语言)
  • [硬件电路-59]:电源:电子存储的仓库,电能的发生地,电场的动力场所
  • 手推OpenGL相机的正交投影矩阵和透视投影矩阵(附源码)
  • 【AI】文生图文生视频
  • 第三章自定义检视面板_创建自定义编辑器类_编辑器操作的撤销与恢复(本章进度3/9)
  • 使用pnpm安装项目的生产依赖dependencies和开发依赖devDependies及pnpm工作空间等简单使用方法说明
  • Function
  • Qwen3-8B 与 ChatGPT-4o Mini 的 TTFT 性能对比与底层原理详解
  • Docker实战:使用Docker部署envlinks极简个人导航页
  • Springboot美食分享平台
  • 【Kafka】深入理解 Kafka MirrorMaker2 - 实战篇
  • Mac m系列 VMware Fusion虚拟机安装ARM contos
  • host.equiv,.rhosts,inetd.conf文件的作用
  • Python应用进阶DAY10--模块化编程概念(模块、包、导入)及常见系统模块总结和第三方模块管理
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘beautifulsoup4’问题
  • 响应式编程入门教程第九节:UniRx 高级特性与自定义
  • python doipclient库
  • 学习C++、QT---30(QT库中如何自定义控件(自定义按钮)讲解)
  • XSS知识总结
  • Ajax简单介绍及Axios请求方式的别名
  • MyBatis从浅入深
  • SQL中的EXPLAIN命令详解
  • python的pywebview库结合Flask和waitress开发桌面应用程序简介
  • HarmonyOS 网络请求优化实战指南:从0到1写出流畅不卡顿的应用!
  • `tidyverse` 中涉及的函数及其用法
  • [Python] -项目实战8- 构建一个简单的 Todo List Web 应用(Flask)