反射
一、定义
通过字节码文件来操作java的类的方式,称为反射
二、核心内容
通过Class类来对class文件进行操作。
-
获得class对象
- 通过类名以及导包获得:
Class clazz = TestClass.class;
- 通过全路径名获得:
Class clazz = Class.forName("com.xuetang9.chapter18.TestClass");
- 通过对象获得:
Class clazz = "abc".getClass();
- 通过类名以及导包获得:
-
获得class文件对应的类名:
clazz.getName()
注意:获得的是全路径名,如 java.lang.String -
获得class文件对应的类的构造方法
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
// 得到构造方法的名字
String constructorName = constructor.getName();
// 得到构造方法的参数个数
int paramCount = constructor.getParameterCount();
System.out.printf("构造方法的名称:%s 参数个数:%s %n", constructorName,paramCount);
}
- 获得class文件对应的类的属性(字段)
Field[] fields = clazz.getFields();
for (Field field : fields) {
// 得到属性名
String fieldName = field.getName();
// 得到属性的类型
Class fieldType = field.getType();
// 得到属性的修饰符
int modfier = field.getModifiers();
System.out.printf("属性:%s 类型:%s 修饰符:%s %n", fieldName,fieldType,modfier);
}
- 获得class文件对应的类的方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
// 得到方法名称
String methodName = method.getName();
// 得到方法参数的个数
int paramCount = method.getParameterCount();
// 得到返回值类型
Class returnType = method.getReturnType();
// 显示
System.out.printf("方法名:%s 参数个数: %s 返回值类型:%s %n",methodName, paramCount, returnType);
}
三、核心使用方法
- 通过反射新建对象(无参构造)
Object object = clazz.newInstance();
- 新建对象(有参构造)
// values为Object数组,存放构造方法所需参数
Class[] paramTypes = new Class[values.length];
for (int i = 0; i < values.length; i++) {
paramTypes[i] = values[i].getClass();
}
Constructor constructor = clazz.getConstructor(paramTypes);
object = constructor.newInstance(values);
- 改变对象的属性的值
/**
* 设置某个对象的属性的值
* @param object 要操作的某个对象
* @param propName 要改变的属性的名字
* @param value 改变后的属性的值
*/
public static void setPropertyValue(Object object, String propName, Object value) {
// 得到对象对应的Class信息
Class clazz = object.getClass();
try {
// 从Class信息中获取属性对象
Field field = clazz.getDeclaredField(propName);
// 设置属性访问权限 (可以访问控制私有属性)
field.setAccessible(true);
// 将对象的属性从新赋值
field.set(object, value);
} catch (Exception e) {
e.printStackTrace();
}
}
- 得到某个属性的值
/**
* 得到某个属性的值
* @param object 要操作的某个对象
* @param propName 要得到的属性的名字
* @return
*/
public static Object getPropertyValue(Object object, String propName) {
// 得到对象对应的Class信息
Class clazz = object.getClass();
try {
// 从Class信息中获取属性对象
Field field = clazz.getDeclaredField(propName);
// 设置属性访问权限
field.setAccessible(true);
// 得到对象的属性
return field.get(object);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
四、注意点
- 同一个类获得的Class对象是相同的
Class clazz1 = String.class;
Class clazz2 = Class.forName("java.lang.String");
Class clazz3 = "123".getClass();
System.out.println(clazz1 == clazz2);
System.out.println(clazz1 == clazz3);
结果:clazz1 == clazz2 == clazz3