java学习笔记:反射

本文详细介绍了Java中类的加载过程,以及反射机制如何动态获取和使用类的构造方法、属性和方法。特别强调了如何处理私有成员的访问,包括使用`setAccessible`方法。还提到了反射在泛型擦除和配置文件中的应用。
摘要由CSDN通过智能技术生成

One Day Day 的


一、类的加载

  1. 加载 头次用到该类的时候会先加载到内存,生成一个class文件
  2. 检验 加载进去之后会检验是否符合语法规范之类的
  3. 初始化 用该类做事情

二、反射机制

在运行状态下,动态的获得一个类的信息,并且调用实例的属性和方法,我们称为java的反射机制

2.1 获取Class对象的三种方法

		//1.通过Class类的静态方法:forName("全限定路径名")
        Class<?> studentClass1 = Class.forName("Student");
        //2. 通过类的class静态属性
        Class<Student> studentClass2 = Student.class;
        //3. 通过实例的getClass()方法
        Student student = new Student(1,"idiot");
        Class<? extends Student> studentClass3 = student.getClass();

2.2 获得构造方法,属性和方法

2.2.1获得构造方法Constructor

方法说明
public Constructor<T> getConstructor(Class<?>… parameterTypes)获取public修饰的指定参数类型所对应的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes)获取指定参数类型所对应的任意构造方法
public Constructor<?>[] getConstructors()获取所有公共的构造方法
public Constructor<?>[] getDeclaredConstructors()获取所有构造方法

2.2.2 获取属性Field

方法说明
public Field getField(String name)获取public修饰的指定名称变量
public Field getDeclaredField(String name)获取指定名称的任意变量
public Field[] getFields()获取所有公共的变量
public Field[] getDeclaredFields()获取所有变量

2.2.3 获取方法Method

方法说明
public Method getMethod(String name, Class<?>… parameterTypes)获取指定名称和参数类型的一个public修饰的方法
public Method getDeclaredMethod(String name, Class<?>… parameterTypes)获取指定名称和参数类型的一个任意方法
public Method[] getMethods()获取所有public修饰的方法
public Method[] getDeclaredMethods()获取所有方法

2.3 使用

使用的时候会发现私有的不让用,这时候我们需要使用setAccessible(boolean flag)方法暴力访问。flag = true取消权限检查

2.3.1 构造方法的使用newInstance(Object… initargs)

//先获取构造方法
Constructor<?> constructor = studentClass1.getConstructor(int.class, String.class);
//利用constructor中的newInstance(Object... initargs)方法创建实例,注意到返回值是Object类
Object idiot = constructor.newInstance(1, "idiot");
//因此我们进行强转
Student s = (Student) idiot;

接下来要展示暴力访问

Constructor<?> constructor = studentClass1.getDeclaredConstructor();
Object idiot = constructor.newInstance();
Student s = (Student) idiot;

给出以下报错信息,原因是无参构造是私有构造方法

Exception in thread “main” java.lang.IllegalAccessException: class Demo cannot access a member of class Student with modifiers “private”
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:355)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:639)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:490)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at Demo.main(Demo.java:19)

这时候我们需要使用setAccessible(boolean flag)方法暴力访问。flag = true取消权限检查

Constructor<?> constructor = studentClass1.getDeclaredConstructor();
//看到了没,就是它取消了权限检查
constructor.setAccessible(true);
Object idiot = constructor.newInstance();
Student s = (Student) idiot;

2.3.2 属性的使用get(Object o)和set(Object o,Object value)

//和上面的很像的
Field name = studentClass1.getField("name");
//这个name是一个Field对象
System.out.println(name);

通过get(Object o)方法获得值,set(Object o,Object value)方法设置值

Field name = studentClass1.getField("name");
System.out.println(name);
//得到null是正常的,这个s是无参构造出来的,用上面的student就没问题了
System.out.println(name.get(s));
name.set(s,"愚者");
//可以看到我们直接修改了值
System.out.println(s.name);
//获得私有属性,就取消下权限,和获取时的方法有差别,剩下的完全一样。
Field id = studentClass1.getDeclaredField("id");
id.setAccessible(true);

2.3.3 方法的调用invoke(Object obj,Object… args)

Method method = studentClass1.getMethod("ggM", String.class);
//s是实例对象,上面set和get哪个也是要给一个实例对象
Object fanHuiZhi = method.invoke(s, "我是方法的参数");
//确定返回值类型的情况下可以强转的
System.out.println(fanHuiZhi);
Method method = studentClass1.getDeclaredMethod("syM", String.class);
method.setAccessible(true);
Object fanHuiZhi = method.invoke(s, "我是方法的参数");
//确定返回值类型的情况下可以强转的
System.out.println(fanHuiZhi);

三、反射练习

3.1 泛型擦除

编译后的.class文件没有泛型的约束,所以可以利用反射去添加编译阶段不让添加的东西。

3.2 反射配置文件

这好像是一个很有用的知识点,但是目前只能了解

嘿嘿嘿,练习…就是练习…但是我还没有练,练了以后写在评论区吧。想看我写的可以催一下我……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值