package zy.refactor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
* 反射:主要作用于访问一个类的私有字段和私有方法
* 使用流程1(已知类的字段以及方法):
* A:获取对象Class
* B:实例化对象
* C:根据字段名反射私有字段 class.getDeclaredField(字段名)
* D:打开允许访问的开关 setAccessible(true);
* E:赋值(set): name.set(dog, "二哈"); 访问(get): name.get(dog)
* F:根据方法名反射私有方法cls.getDeclaredMethod("eat", String.class, String.class);
* G:打开开关
* H:访问私有方法 m2.invoke(dog, "阿拉斯加", "全家桶");
* 使用流程2(不知道类的字段及方法):
* A:获取对象Class
* B:根据Class反射所有的字段名称以及类型(循环Field[]得出字段名以及字段类型)
* C:根据Class反射构造方法
* D:根据构造方法创建对象(object类型)
* E:根据B中得到的字段名称和类型分别定义Field并打开开关然后给私有字段赋值 Field name = cls.getDeclaredField("name");
* F:访问私有字段
* G:反射私有方法(也可以反射Method[]数组 循环得出方法名等,类似反射字段数组)
* H:打开开关并访问私有方法
*/
/**
* 反射的应用
*
* @author zy
* @version 1.0
*/
public class RefectorDemo {
public static void main(String[] args) throws Exception {
// 获取类的字节码对象(获取对象Class) 以下方法都可以
// Class cls = dog.getClass();
// Class cls = Dog.class;
Class cls = Class.forName("zy.refactor.Dog");
// -------------------------------------------------------方式1
// 创建对象
Dog dog = new Dog();
// 反射私有字段
Field name = cls.getDeclaredField("name");
Field age = cls.getDeclaredField("age");
// 打开开关
name.setAccessible(true);
age.setAccessible(true);
// 赋值
name.set(dog, "二哈");
age.set(dog, 6);
// 访问私有字段
System.out.println(name.get(dog) + "--" + age.get(dog));
// 反射私有方法
Method m1 = cls.getDeclaredMethod("eat");
Method m2 = cls.getDeclaredMethod("eat", String.class, String.class);
// 打开开关
m1.setAccessible(true);
m2.setAccessible(true);
// 访问私有方法
m1.invoke(dog, null);
m2.invoke(dog, "阿拉斯加", "全家桶");
// -----------------------------------------------------------------下面是方式2
System.out.println("----------------------------");
// 反射所有的字段名称
Field[] fields = cls.getDeclaredFields();
// 此时已经知道一共有多少字段分别为什么 可以根据字段名称以及字段类型 进行赋值
for (Field f : fields) {
System.out.println(f.getType() + "--" + f.toString());
}
// 此时我们已经知道Dog类中有两个私有的字段,分别为String类型的name和int类型的age;下面我们就直接用了
//反射所有方法 和反射字段基本类似
Method[] methods = cls.getDeclaredMethods();
for (Method m : methods) {
System.out.println(m.getName());
}
// 反射构造方法
Constructor con1 = cls.getConstructor();
Constructor con2 = cls.getConstructor(String.class, int.class);
// 根据反射的构造方法创建对象
Object obj1 = con1.newInstance();// 创建对象
Object obj2 = con2.newInstance("泰迪", 3);// 创建对象并赋值
// obj1用的空构造方法
// 给obj1对象的字段赋值(因为上面循环fields已经知道了这两个字段的name和type,这里就直接赋值了)
name.set(obj1, "金毛");
age.set(obj1, 4);
// 访问私有字段
System.out.println(name.get(obj1) + "--" + age.get(obj1));// 金毛--4
System.out.println(name.get(obj2) + "--" + age.get(obj2));// 泰迪--3
// 访问私有方法
m1.invoke(obj1, null);
m2.invoke(obj1, name.get(obj1), "金毛的食物");
m1.invoke(obj2, null);
m2.invoke(obj2, name.get(obj2), "泰迪的食物");
}
}
package zy.refactor;
/*
* 反射用的dog类
*/
public class Dog {
private String name;
private int age;
public Dog() {
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
private void eat() {
System.out.println("狗吃骨头");
}
private void eat(String name, String food) {
System.out.println(name + "吃" + food);
}
}