通过反射,我们可以在运行时获取任意一个类的所有属性和方法,并且可以调用它们。
JDK动态代理,注解的实现。
优点:代码更加灵活。
缺点:安全问题,性能问题。
Class类,保存程序运行时某个对象的所有信息。
获取Class类的方法
// 通过对象实例获取
obj.getClass();
// 通过全类名获取
Class.forName("cn.com.Example");
// 通过具体的类获取
Example.class;
// 通过类加载器传入全类名获取
ClassLoader.getSystemClassLoader().loadClass("cn.com.Example");
getFileds()、getMethods()、getConstructors()方法分别返回这个类的公共字段、方法和构造器的数组(包括超类)。
public Field getField(String name)
获取指定字段public Method getMethod(String name, Class<?>... parameterTypes)
获取指定方法public Constructor<T> getConstructor(Class<?>... parameterTypes)
获取指定构造器补充 parameterTypes:因为方法或构造器可能同名,所有用 parameterTypes(传入参数类型的 Class 类) 区分不同的方法和构造器。
getDeclareFileds()、getDeclareMethods()、getDeclareConstructors() 方法返回所有字段、方法和构造器的数组(不包括超类)。对于单个字段、方法和构造器获取参考前面。
怎么使用?
对于 Filed 类:
public Object get(Object obj)
获取对象实例该字段的值。
public void set(Object obj, Object value)
设置对象实例该字段的值。value是设置的新值。
对于 Method 类:
public Object invoke(Object obj, Object... args)
调用对象实例的该方法。args是该方法需要的参数。对于 Constructor 类:
public T newInstance(Object ... initargs)
根据构造器构造一个对象实例。initargs构造方法需要的参数实战
public class Employee {
private String name;
private double salary;
public Employee() {
}
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return this.name;
}
public double raiseSalary(double raise) {
return this.salary + raise;
}
public String toString() {
return "name:" + this.name + ",salary:" + this.salary;
}
}
public class Main {
public static void main(String[] args) throws Exception {
Employee jim = new Employee("Jim", 1000.0);
Field nameFiled = Employee.class.getField("name");
String o = (String) nameFiled.get(jim);
System.out.println(o); // Jim
nameFiled.set(jim, "jim");
System.out.println(jim); // name:jim,salary:1000.0
Method m1 = Employee.class.getMethod("getName");
Method m2 = Employee.class.getMethod("raiseSalary", double.class);
String name = (String) m1.invoke(jim);
double salary = (double) m2.invoke(jim, 2000);
System.out.println("name=" + name + ",salary=" + salary); // name=jim,salary=3000.0
System.out.println(jim); // name:jim,salary:1000.0
Constructor<Employee> constructor = Employee.class.getConstructor(String.class, double.class);
Employee employee = constructor.newInstance("BBBB", 1000);
System.out.println(employee); // name:BBBB,salary:1000.0
}
}