能够分析类能力的程序称为反射
1、反射机制的作用
- 在运行时分析类的能力
- 在运行时检查对象
- 实现泛型数组操作代码
- 利用Method对象
2、Class类
- Java运行时系统始终为所有对象维护一个运行时类标识,这个信息会跟踪每个对象所属的类。
- 虚拟机利用运行时类型信息选择要执行的正确的方法
- 可以使用Class类访问这些信息
- Class类实际上是一个泛型类,Employee.class的类型是Class<Employee>
Employee e;
Class cl = e.getClass(); // 如果e是Employee则cl是Employee,如果e是Manager则cl是Manager
- 如果有一个Class类型的对象,可以用它来构造类实例
var className = "java.util.Random";
Class cl = Class.forName(className);
Object obj = cl.getConstructor().newInstance(); // 如果没有无参构造器会抛出异常
3、利用反射分析类的能力
- Field 类的描述字段 getFields
- Method 类的方法 getMethods
- Constructor 类的构造器 getConstructor
var harry = new Employeee("Harry P",5000,10,1,1989);
Class cl = harry.getClass(); // Employee
Field f = cl.getDeclaredField("name"); // Employee的name这个字段
Object v = f.get(harry); // 获取的是harry的name字段的值
4、反射案例
扩展一个Array数组
- 目的是扩展一个已经填满的数组
public static Object[] badCopyOf(Object[] a, int newLength) // not useful 因为Object没法转换成其他类型的数组
{
Object[] newArray = new Object[newLength];
System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
return newArray;
}
- 为了实现一个通用的扩展数组的方法,可以用反射在运行的时候获取数组里元素的类型
public static Object goodCopyOf(Object a, int newLength)
{
Class cl = a.getClass();
if (!cl.isArray()) return null;
Class componentType = cl.getComponentType(); // 返回数组中元素的Class对象,如果不是Class对象那么返回null
int length = Array.getLength(a);
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
return newArray;
}
- Array.newInstance
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);
}
调用任意方法和构造器
- Field类的get方法可以查看一个对象的字段
- Method类可以通过invoke方法调用包装在当前Method对象中的方法,invoke的参数和返回值必须是Object类型,Obejct invoke(Object obj, Object... args),如果是静态方法,第一个参数可以是null
import java.lang.reflect.*;
public class MethodTableTest
{
public static void main(String[] args) throws Exception
{
// get method pointers to the square and sqrt methods
Method square = MethodTableTest.class.getMethod("square", double.class);
Method sqrt = Math.class.getMethod("sqrt", double.class);
printTable(1, 10, 10, square);
printTable(1, 10, 10, sqrt);
}
public static double square(double x)
{
return x * x;
}
public static void printTable(double from, double to, int n, Method f)
{
System.out.println(f);
double dx = (to - from) / (n - 1);
for (double x = from; x <= to; x += dx)
{
try
{
double y = (Double) f.invoke(null, x); //这里用到invoke
System.out.printf("%10.4f | %10.4f%n", x, y);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
- Constructor类,获取类的构造器,构造对象
Class cl = Random.class;
Constructor cons = cl.getConstructor(long.class);
Object obj = cons.newInstance(42L);
网友评论