反射概述
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。本质就是 操作字节码文件。
反射相关的类(简述)
-
java.lang.Class
整个类的字节码,代表整个类【一个类型】 -
java.lang.reflect.Method
字节码中的方法字节码,代表类中的方法 -
java.long.reflect.Constructor
字节码中的构造方法字节码,代表类中的构造方法 -
java.long.reflect.Field
字节码中的属性字节码,代表类中的成员变量和实例变量
获取字节码文件(★★★★★)
- 第一种:Class clazz = Class.forName(“带包名的完整类名”);
clazz_1 = Class.forName("java.lang.String"); //clazz_1代表String.calss文件,或者说代表String类型
- 第二种:Class clazz = 对象.getClass();
Date date = new Date();
Class clazz_5 = date.getClass(); //任何一个对象都有getClass()方法
- 第三种:Class clazz = 任何类型.class;
Class clazz_7 = Integer.class; //clazz_7代表Integer类型
反射机制创建对象
- 获取字节码文件
- 通过
Class
对象调用newInstance()
完成对象的创建- 调用
newInstance()
方法必须保证 类有无参构造方法
- 调用
Class<?> classTeacher = Class.forName("reflectdemo_02.Teacher");
Object o = classTeacher.newInstance();
System.out.println(o); // reflectdemo_02.Teacher@1b6d3586
反射相关的类(详解)
(1)java.lang.Class 类 (★★★★★)
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 枚举是一种类,注释是一种接口。Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造。
常用方法
(2)java.long.reflect.Field 类 (★★★)
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 反射的字段可能是一个类(静态)字段或实例字段。
常用方法
Object get(Object obj)
返回指定对象上此 Field 表示的字段的值。int getInt(Object obj)
获取 int 类型或另一个通过扩展转换可以转换为 int 类型的基本类型的静态或实例字段的值。int getModifiers()
以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符。String getName()
返回此 Field 对象表示的字段的名称。Class<?> getType()
返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。int hashCode()
返回该 Field 的哈希码。void set(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。void setInt(Object obj, int i)
将字段的值设置为指定对象上的一个 int 值。String toString()
返回一个描述此 Field 的字符串。
(3)java.long.reflect.Method 类 (★★★)
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
常用方法
int getModifiers()
以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。String getName()
以 String 形式返回此 Method 对象表示的方法名称。Class<?>[] getParameterTypes()
按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。Class<?> getReturnType()
返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。int hashCode()
返回此 Method 的哈希码。Object invoke(Object obj, Object... args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。(★★★)String toString()
返回描述此 Method 的字符串。
(4)java.long.reflect.Constructor 类 (★★)
Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
常用方法
int getModifiers()
以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。String getName()
以字符串形式返回此构造方法的名称。Class<?>[] getParameterTypes()
按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。TypeVariable<Constructor<T>>[] getTypeParameters()
按照声明顺序返回一组 TypeVariable 对象,这些对象表示通过此 GenericDeclaration 对象所表示的一般声明来声明的类型变量。int hashCode()
返回此 Constructor 的哈希码。T newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。(★★★)String toString()
返回描述此 Constructor 的字符串。
通过反射机制反编译
package reflectdemo_06;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ResourceBundle;
/**
* 使用反射机制反编译类【成员属性,成员方法,构造方法】
* @Author Nigori
* @Create 2020/9/3
*/
public class DecompilationAllReflectTest {
public static void main(String[] args) throws Exception {
//获取资源文件
ResourceBundle resource = ResourceBundle.getBundle("classinfo");
String userClass = resource.getString("userClass");
//获取字节码文件
Class<?> aClass = Class.forName(userClass);
/**
* 反编译【字符串拼接】
*/
//创建StringBuilder
StringBuilder builder = new StringBuilder();
//类结构反编译
builder.append(Modifier.toString(aClass.getModifiers())); //类修饰符
builder.append(" class ");
builder.append(aClass.getSimpleName()); //类名
builder.append(" {\n");
//字段反编译
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
builder.append("\t");
builder.append(Modifier.toString(field.getModifiers())); //字段修饰符
builder.append(" ");
builder.append(field.getType().getSimpleName()); //字段类型
builder.append(" ");
builder.append(field.getName()); //字段名
builder.append(";\n");
}
builder.append("\n");
//构造方法反编译
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors(); //构造方法列表
for (Constructor<?> constructor : declaredConstructors) {
builder.append("\t");
builder.append(Modifier.toString(constructor.getModifiers())); //构造方法修饰符
builder.append(" ");
builder.append(aClass.getSimpleName()); //构造方法名
builder.append("(");
//拼接参数列表
Class<?>[] parameterTypes = constructor.getParameterTypes(); //参数列表
for (Class<?> parameterType : parameterTypes) {
builder.append(parameterType.getSimpleName()); //参数类型
builder.append(",");
}
if (parameterTypes.length > 0) {
builder.deleteCharAt(builder.length() - 1);
}
builder.append(") {...}\n");
}
builder.append("\n");
//成员方法反编译
Method[] declaredMethods = aClass.getDeclaredMethods(); //成员方法列表
for (Method method : declaredMethods) {
builder.append("\t");
builder.append(Modifier.toString(method.getModifiers())); //方法修饰符
builder.append(" ");
builder.append(method.getReturnType().getSimpleName()); //方法返回值类型
builder.append(" ");
builder.append(method.getName()); //方法名
builder.append("(");
//拼接参数列表
Class<?>[] parameterTypes = method.getParameterTypes(); //方法参数列表
for (Class<?> type : parameterTypes) {
builder.append(type.getSimpleName()); //方法参数类型
builder.append(",");
}
if (parameterTypes.length > 0) {
builder.deleteCharAt(builder.length() - 1);
}
builder.append(") {...}\n");
}
builder.append("}");
System.out.println(builder);
}
}
输出结果
public class UserService {
private String userName;
private String passWord;
protected String userNo;
public UserService(String,String,String) {...}
public UserService(String,String) {...}
public UserService(String) {...}
public UserService() {...}
public String toString() {...}
public void logout() {...}
public boolean login(String,String) {...}
}
通过反射机制创建对象(★★★★★)
1. 获取类的字节码
2. 通过字节码获取有/无参构造方法
3. 调用newInstance()
方法创建对象
Class<?> aClass = Class.forName("reflectdemo_07.User"); //获取类的字节码
//无参构造方法创建对象
Object o = aClass.newInstance();
System.out.println(o);
//有参构造方法创建对象【推荐】
Constructor<?> newObj = aClass.getDeclaredConstructor(int.class,String.class);
Object obj = newObj.newInstance(1015, "小王");
System.out.println(obj);
反射机制设置/获取字段值(★★★★★)
1. 获取类的字节码
2. 创建对象
3. 获得指定的字段名
4. 使用字段对象.set(Object obj,Object value)
方法设置值
5. 使用字段对象.get(Object obj)
方法获取值
package reflectdemo_04;
import java.lang.reflect.Field;
/**
* 通过反射机制设置/获取属性值
* @Author Nigori
* @Create 2020/9/2
*/
public class ReflectGetValueTest {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("reflectdemo_04.Student");
Object student = aClass.newInstance();
Field teacherName = aClass.getDeclaredField("teacherName");
teacherName.set(student,"王老师");
System.out.println("teacherName:" + teacherName.get(student));
Field studentNo = aClass.getDeclaredField("studentNo");
studentNo.setAccessible(true); //字段为private时,打破封装,否则在设置/取值值时抛IllegalAccessException
studentNo.set(student,10051);
System.out.println("studentNo:" + studentNo.get(student));
}
}
反射机制调用方法(★★★★★)
1. 获取类的字节码
2. 获得指定方法 【方法名,参数类型】
3. 使用invoke(Object obj, Object... args)
调用方法
调用方法四要素:
- 方法名
- 对象
- 实参
- 返回值
Class<?> aClass = Class.forName("reflectdemo_07.User"); //获取类的字节码
Object obj = aClass.newInstance(); //创建对象
Method show = aClass.getDeclaredMethod("show", int.class); //获得指定方法
Object retValue = show.invoke(obj,12112); //方法的调用
System.out.println(retValue);
反射机制获取超类
package reflectdemo_07;
/**
* @Author Nigori
* @Create 2020/9/3
*/
public class SetGetTest {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("java.lang.String");
//获取String类的超类
Class<?> superclass = aClass.getSuperclass();
System.out.println(superclass);
//获取String类实现的所有接口
Class<?>[] interfaces = aClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface.getName());
}
}
}