反射
反射的概述
反射是可以用来解剖类并操作类的所有成员(静态/非静态成员变量、构造函数、静态/非静态方法)的一种机制,可以无视成员定义的访问权限
反射的用法
获取类的字节码(Class类)对象来实现对类的所有成员的操作
反射的应用场景
Java集成开发环境IDE(Eclipse、IDEA等),各种框架的开发
Class类
Class类对象的获取方法
1. 通过类名.class获取(也可以通过基本数据类型名.class)
2. 通过对象名.getClass()获取
3. Class.forName(类名)获取
Notice:如果使用第三种方法获取字节码对象,forName() 的参数应为类的全名,即包名.类名
Class类常用方法
1. String getSimpleName() 获取类名
2. String getName() 获取类全名(类所在的包名.类名)
3. T newInstance() 创建对象(要求类需要有非私有且无参数的构造函数)
Notice:如果一个类的无参构造是private的你仍然用上面的newInstance()创建对象,将出现如下异常:
在反射机制中,类的所有成员均可以成为对象,这些表示成员的对象分别被抽象成Constructor类、Method类、Package类、Field类等。
Constructor类
概述
Constructor类集成了构造函数的信息(参数列表、访问权限、包名等),在反射机制中,每一个构造函数都是一个Constructor对象。
应用
利用Constructor类可以获取类的所有构造函数以及创建对象(即便构造函数是私有的)
方法
1. T newInstance(Object... initargs) 创建一个对象,参数列表要与构造函数定义的参数列表相匹配
2. void setAccessible(boolean flag) 如果参数为true就暴力解除访问权限锁
Class类中与之相关的方法
1. Constructor getConstructor(Class <?>... parameterTypes) 获取类中单个公共的构造函数,可以不带参数来获取公共无参构造
2. Constructor[] getConstructors() 获取类中所有公共构造函数
3. Constructor getDeclaredConstructor(Class <?>... parameterTypes) 获取类中单个任意访问权限的构造函数(public、protected、package、private)
4. Constructor[] getDeclaredConstructors() 获取类中所有的构造函数,无视访问权限
package com.reno.d0822;
import java.lang.reflect.Constructor;
class Something {
private String name;
private Something() {}
public Something(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Work {
/**
* @description TODO
* @author Reno
* @date 2022/8/23 1:19
* @version 1.0.0
*/
public static void main(String[] args) throws Exception {
Class<Something> aClass = Something.class;
Constructor<Something> constructor = aClass.getDeclaredConstructor();
System.out.println(constructor);
//对于private的构造函数,操作前必先解除访问锁
constructor.setAccessible(true);
Something something = constructor.newInstance();
System.out.println(something);
//无视访问权限锁,一次性获取所有构造函数
Constructor<?>[] cons = aClass.getDeclaredConstructors();
for (Constructor<?> con : cons) {
System.out.println(con);
}
}
}
总结
1. Java的反射机制是在运行时利用字节码操控类的成员,可以暴力破解成员的访问权限锁,这也就意味着访问权限修饰符只能在编译这一环节确保数据安全
2. 在反射机制所用到的类中,这些方法如果方法名包含名词复数形式,则不需要参数且要用数组接收返回值
3. 利用反射机制确实可以无视访问权限的限制,但对于不能直接访问的成员,必须调用相应成员的setAccessible(true)才可以暴力破解访问权限锁,你才能对成员执行后续操作