概述
- 反射是一种强大的工具,可以用来编写能够动态操纵 Java 代码的程序,通过反射机制我们可以操作字节码文件。反射机制将类的各个部分封装成了对象,在程序运行的过程中我们可以操作这些对象(在操作一个类对象的时候我们可以操作其方法成员变量等)。这样可以使得程序解耦,提高了程序的可扩展性。
Java 代码的三个阶段
- 源代码阶段:编写类文件,然后添加成员变量,成员方法等,代码编译后生成字节码文件,此时代码还未被加载进内存。
- Class 类对象阶段:Class 类对象使用类加载器将字节码文件加载进内存,此时内存中就会产生一个唯一的 Class 类对象来标识这个类中的各项信息,Class 类对象中又包含了描述成员变量的 Field 对象、描述构造方法的 Constructor 对象和描述成员方法的 Method 对象。
- 运行时阶段:new 一个新的类对象。
Class
- 在程序运行的时候,系统始终为所有的对象维护一个运行时的类型标识,这个信息会跟踪每一个对象所属的类,我们使用 Java 中的 Class 类就可以访问这些被记录的信息。
获取 Class 对象的三种方式
- Class.forName("全类名"):将字节码文件加载进内存,配置文件常用
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class cls = Class.forName("java.lang.String");
System.out.println(cls);//class java.lang.String
}
}
- 类名.class:常用于参数的传递
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class cls = Class.forName("java.lang.String");
Class cls1 = String.class;
System.out.println(cls.hashCode());//460141958
System.out.println(cls1);//class java.lang.String
}
}
- 对象.getClass():常用于获取对象字节码
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class cls = Class.forName("java.lang.String");
Class cls1 = String.class;
String str = "";
Class cls2 = str.getClass();
//字节码文件在内存中只被加载一次
//不管使用什么方式获取到的Class对象都是同一个
System.out.println(cls.hashCode());//460141958
System.out.println(cls1.hashCode());//460141958
System.out.println(cls2);//class java.lang.String
}
}
Class 类常用 API
- 获取 public 修饰的成员变量
//获取 public 修饰的成员变量
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class cls = Class.forName("java.lang.String");
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
Field field = cls.getField("CASE_INSENSITIVE_ORDER");
System.out.println(field.getName());
}
}
//获取所有的成员变量
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class cls = Class.forName("java.lang.String");
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
Field field = cls.getDeclaredField("hash");
System.out.println(field.getName());
}
}
- 获取构造函数
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//得到所有公共的构造函数对象
Constructor[] constructors = cls.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//得到特定的公共构造函数对象
Constructor constructor = cls.getConstructor(String.class);
System.out.println(constructor);
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//得到所有的构造函数对象
Constructor[] constructors = cls.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//得到特定的构造函数对象
Constructor constructor = cls.getDeclaredConstructor(String.class);
System.out.println(constructor);
}
}
- 获取成员方法
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//获取所有公共的成员方法
Method[] methods = cls.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取特定的公共的成员方法
System.out.println("-------");
Method method = cls.getMethod("toLowerCase", Locale.class);
System.out.println(method);
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//获取所有的成员方法
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取特定的成员方法
System.out.println("-------");
Method method = cls.getDeclaredMethod("lastIndexOfSupplementary", int.class, int.class);
System.out.println(method);
}
}
- 有关 Class 类的 API
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
System.out.println(cls.getName());//java.lang.String
System.out.println(cls.getSimpleName());//String
//获取父类
Class superclass = cls.getSuperclass();
System.out.println(superclass);//class java.lang.Object
System.out.println(superclass.isInterface());//false
//获取包对象
Package aPackage = cls.getPackage();
System.out.println(aPackage.getName());//java.lang
}
}
Constructor
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//得到所有的构造函数对象
Constructor[] constructors = cls.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
//方法名
System.out.println(constructor.getName());
//修饰符
System.out.println(Modifier.toString(constructor.getModifiers()));
//参数类型
Class[] parameterTypes = constructor.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.print(parameterType.getName() + " ");
}
System.out.println();
System.out.println("-------------------------------------");
}
}
}
//创建对象
public class Main {
public static void main(String[] args) throws Exception {
Class cls = String.class;
String str = (String) cls.newInstance();
}
}
Field
public class Main {
public static void main(String[] args) throws Exception {
String str = "1111";
Class cls = Class.forName("java.lang.String");
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
System.out.println(Modifier.toString(field.getModifiers()));
System.out.println(field.getType().getSimpleName());
System.out.println(field.getName());
//System.out.println(field.get(str));
System.out.println("-----------------------------------------------");
}
}
}
//为对象的成员变量设置值
public class Main {
public static void main(String[] args) throws Exception {
Class cls = String.class;
String str = (String) cls.newInstance();
Field field = cls.getDeclaredField("value");
//不是公共的成员变量是需要暴力反射,默认只能修改非公共成员变量
field.setAccessible(true);
System.out.println(field);
System.out.println(field.get(str));//[C@4554617c
System.out.println(str);//
field.set(str, new char[]{'1', '1'});
System.out.println(field.get(str));//[C@74a14482
System.out.println(str);//11
}
}
Method
public class Main {
public static void main(String[] args) throws Exception {
Class cls = Class.forName("java.lang.String");
//获取所有的成员方法
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
System.out.println(Modifier.toString(method.getModifiers()));
System.out.println(method.getReturnType().getSimpleName());
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType.getSimpleName());
}
//是否有可变参数
System.out.println(method.isVarArgs());
System.out.println(method.getName());
System.out.println("-------------------------");
}
}
}
//执行类方法
public class Main {
public static void main(String[] args) throws Exception {
Class cls = String.class;
String str = (String) cls.newInstance();
Field field = cls.getDeclaredField("value");
field.setAccessible(true);
field.set(str, new char[]{'1', '1'});
Method method = cls.getDeclaredMethod("length");
System.out.println(method.invoke(str));
}
}
配置文件操作类
配置文件
className = java.lang.String
methodName = length
fieldName = value
Properties + IO + 反射
public class Main {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
//方式一:利用当前类获取流,配置文件需要在src目录下
ClassLoader classLoader = Main.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
properties.load(is); //要记得关闭流
//方式二:首先获取文件路径,然后根据路径创建输入流
//配置文件需要在根路径下
// String path = Thread.currentThread().getContextClassLoader().getResource("pro.properties").getPath();
// //System.out.println(path);
// FileReader reader = new FileReader(path);
// properties.load(reader);
Class cls = Class.forName(properties.getProperty("className"));
Object o = cls.newInstance();
Field field = cls.getDeclaredField(properties.getProperty("fieldName"));
field.setAccessible(true);
field.set(o, new char[]{'a', 'b'});
System.out.println(field.get(o));
Method method = cls.getDeclaredMethod(properties.getProperty("methodName"));
System.out.println(method.invoke(o));
}
}
ResourceBundle + 反射
public class Main {
public static void main(String[] args) throws Exception {
//资源绑定器,配置文件需要放在根路径下
ResourceBundle bundle = ResourceBundle.getBundle("pro");
Class cls = Class.forName(bundle.getString("className"));
Object o = cls.newInstance();
Field field = cls.getDeclaredField(bundle.getString("fieldName"));
field.setAccessible(true);
field.set(o, new char[]{'a', 'b'});
System.out.println(field.get(o));
Method method = cls.getDeclaredMethod(bundle.getString("methodName"));
System.out.println(method.invoke(o));
}
}
反射方式反编译类框架
配置文件
className = java.util.ResourceBundle
测试代码
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
//资源绑定器,配置文件需要放在根路径下
ResourceBundle bundle = ResourceBundle.getBundle("pro");
Class<?> cls = Class.forName(bundle.getString("className"));
Package aPackage = cls.getPackage();
//包
if (aPackage != null) System.out.println("package " + aPackage.getName());
System.out.println();
//修饰符
System.out.print(Modifier.toString(cls.getModifiers()) + " ");
//类名
System.out.print(cls.getSimpleName() + " ");
//父类
Class<?> superclass = cls.getSuperclass();
if (!superclass.equals(Object.class)) {
System.out.print( "extends " + superclass.getSimpleName() + " ");
}
//接口
Class<?>[] interfaces = cls.getInterfaces();
StringBuilder _interfaces = new StringBuilder();
if(interfaces.length == 0) {
_interfaces.append("");
} else {
_interfaces.append(" implements ");
}
for (int i = 0; i < interfaces.length; i++) {
_interfaces.append(interfaces[i].getSimpleName());
if (i != interfaces.length - 1) {
_interfaces.append(", ");
} else {
_interfaces.append(" ");
}
}
System.out.println(_interfaces + "{");
System.out.println();
//获取成员变量
getDeclaredFields(cls);
//获取构造方法
getDeclaredConstructors(cls);
//获取成员方法
getMethods(cls);
System.out.println("}");
}
private static void getDeclaredFields(Class<?> cls) {
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.print("\t");
//修饰符
System.out.print(Modifier.toString(field.getModifiers()) + " ");
//数据类型
System.out.print(field.getType().getSimpleName() + " ");
//变量名
System.out.println(field.getName() + ";");
//System.out.println(field);
//System.out.println("----------------");
}
System.out.println();
}
private static void getDeclaredConstructors(Class<?> cls) {
Constructor<?>[] constructors = cls.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
//修饰符
System.out.print("\t");
if (constructor.getModifiers() != 0)
System.out.print(Modifier.toString(constructor.getModifiers()) + " ");
//方法名
System.out.print(cls.getSimpleName() + "(");
//参数
Class<?>[] typeParameters = constructor.getParameterTypes();
StringBuilder _typeParameters = new StringBuilder();
for (int i = 0; i < typeParameters.length; i++) {
if (i != 0) {
_typeParameters.append(", ");
}
_typeParameters.append(typeParameters[i].getSimpleName());
}
System.out.println(_typeParameters + "){};");
//System.out.println(constructor);
//System.out.println("---------------------------");
}
System.out.println();
}
private static void getMethods(Class<?> cls) {
Method[] methods = cls.getMethods();
for (Method method : methods) {
System.out.print("\t");
//修饰符
System.out.print(Modifier.toString(method.getModifiers()) + " ");
//返回值
System.out.print(method.getReturnType().getSimpleName() + " ");
//方法名
System.out.print(method.getName() + "(");
//参数
Class<?>[] parameterTypes = method.getParameterTypes();
StringBuilder _parameterTypes = new StringBuilder();
for (int i = 0; i < parameterTypes.length; i++) {
if (i != 0) {
_parameterTypes.append(", ");
}
_parameterTypes.append(parameterTypes[i].getSimpleName());
}
System.out.println(_parameterTypes + "){};");
//System.out.println(method);
//System.out.println("------------------------");
}
System.out.println();
}
}