反射总结

0- 一个类被类加载器加载到JVM(内存)中后,生成了多个对象:Class Constructor Method Field

1- 三种创建字节码文件对象

 

         * a:Object类的getClass()方法,判断两个对象是否是同一个字节码文件

         * b:静态属性class,锁对象

         * c:Class类中静态方法forName(),读取配置文件

 

 

2- 通过字节码文件对象创建该类对象

(通过反射获取带参构造方法并使用)

    *a: newInstance()

    *b:  Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象

        

  Class clazz = Class.forName("com.th.reflect.Person");
  Constructor[] constructors = clazz.getConstructors();//获取所有的构造方法
Constructor constructor = clazz.getConstructor(Class.String, Class.Integer);//获取固定的有参构造

3- 通过反射获取私有成员变量并使用

     其中使用到的类:

    Class : 获取到字节码文件对象;

            forName();

            getConstructor();

            getField("xxx");                  //只能获取公有的字段

            getDeclaredField("xxx");   //暴力获取私有字段

    Constructor:通过字节码对象获取到构造方法;

            newInstance(param1,param2,......);

    Field : 通过字节码对象获取对象的属性;

            setAccessible(true); //去除私有字段的私有权限

            set(Object o,"value");//修改该对象的该属性的值

Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class);  //1- 获取有参构造
Person p = (Person) c.newInstance("张三",23);          //2- 通过有参构造创建对象

//因为name属性为私有的,用下面注释掉的代码无法获取
//Field f = clazz.getField("name");                         //3- 获取姓名字段
//f.set(p, "李四");                                   //4- 修改姓名的值
Field f = clazz.getDeclaredField("name");           //5- 暴力反射获取字段
f.setAccessible(true);                               //6- 去除私有权限
f.set(p, "李四");                                               //7- 修改字段值

System.out.println(p);

4- 通过反射获取方法并使用

public static String getClassName() throws IOException {
    String className = null;
    Properties properties = new Properties();
    properties.load(new FileInputStream("config.properties"));
    className = properties.getProperty("className");
    return className;
}
String className = getClassName();
Class clazz = Class.forName(className);
Constructor c = clazz.getConstructor(String.class, Integer.class);
Person p = (Person) c.newInstance("Tom1",26);

//1- 获取非私有无参数无返回值的方法并调用
Method eat = clazz.getMethod("eat");
eat.invoke(p);

//2- 获取私有的无参数无返回值的方法并使用
Method sleep = clazz.getDeclaredMethod("sleep");
sleep.setAccessible(true);
sleep.invoke(p);

//3- 获取有参数的方法
Method eat1 = clazz.getMethod("eat", Apple.class);
eat1.invoke(p,new Apple());

//4- 获取有返回值的方法
Method getNameAndAge = clazz.getMethod("getNameAndAge");
String nameAndAge = (String) getNameAndAge.invoke(p);
System.out.println(nameAndAge);

5- 集合里面不一定只能存储一种类型的数据。

ArrayList<Integer> list = new ArrayList<>();
list.add(111);
list.add(222);
//list.add("abc");

Class<ArrayList> clazz = ArrayList.class;                       //
Method add = clazz.getMethod("add", Object.class);       // 获取add方法
Person p = new Person("Tom1", 27);
add.invoke(list,p);
add.invoke(list,"abc");
System.out.println(list);

[111, 222, Person{name='Tom1', age=27}, abc]

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值