一、反射
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。也就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
反射就是把Java类中的各种成分映射成一个个的Java对象。
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
如图是类的正常加载过程:反射的原理在与class对象。
二、应用
基础语法:
获取class对象的方式:(字节码对象)
1.class.forName(“全类名”):将字节码文件加载进内存,返回class对象
2.类名.class:通过类名的属性class获取
3.对象.getClass():getClass()方法在Object类中定义。
*获取功能
* 1.获取成员变量:
* Field[] getFields(): 获取所有public修饰的成员变量
* Field[] getField(String name): 获取指定名称的 public修饰的成员变量
* Field[] getDeclaredFields(): 提取所有的成员变量,不考虑修饰符
* Field[] getDeclaredField(String name)
*
* 2.获取构造方法:
* Constructor<?>[] getConstructors()
* Constructor[] getConstructor(类<?>…parameterTypes)
*
* Constructor<?>[] getDeclaredConstructors()
* Constructor[] getDeclaredConstructor(类<?>…parameterTypes)
*
* 3.获取成员方法:
* Method[] getMethods()
* Method getMethod(String name,类<?>…parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name,类<?>…parameterTypes)
*
* 4.获取类名:
* String getName()
*
* Field:成员变量
* 操作:
* 1.设置值
* void set(Object obj, Object value)
* 2.获取值
* get(Object obj)
* 3.忽略访问权限修饰符的安全检查
* setAcessible(true):暴力反射
*
* Constrcutor构造方法
* 创建对象:
* T newInstance(Object… initargs)
* 如果使用空参数构造方法创建对象,操作可以简化:class对象的newInstance方法
*
* Method:方法对象
* 执行方法:
* Object invoke(Object obj,Object… args)
*
* 获取方法名称
*/
代码展示:
//Person类
public class Person {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", a=" + a + "]";
}
public void eat() {
System.out.println("吃");
}
public void eat(String food) {
System.out.println("吃" + food);
}
}
//反射的演示
//0.获取class对象
Class personClass = Person.class;
Field[] fields = personClass.getFields();
for(Field field:fields) {
System.out.println(field);
}
Field a = personClass.getField("a");
System.out.println(a);
//获取成员变量a的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
a.set(p, "张三");
System.out.println(p);
System.out.println("=======================");
//Field[] getDeclaredFields() :提取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for(Field field:declaredFields) {
System.out.println(field);
}
Field d = personClass.getDeclaredField("d");
//忽略访问权限的安全检查(暴力反射)
d.setAccessible(true);
Object value2 = d.get(p);
System.out.println(value2);
System.out.println("=======================");
//Constructor<T>[] getDeclaredConstructor(类<?>....parameterTypes)
Constructor constructor = personClass.getConstructor(String.class,int.class);
System.out.println(constructor);
//创建对象
Object person = constructor.newInstance("张三",23);
System.out.println(person);
System.out.println("=======================");
//获取指定名称的方法
Method eat_method = personClass.getMethod("eat");
Person p2 = new Person();
//执行方法
eat_method.invoke(p2);
Method eat_method2 = personClass.getMethod("eat",String.class);
eat_method2.invoke(p2, "饭");
//获取类名
String className = personClass.getName();
System.out.println(className);
运行结果