欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

反射调用属性成员

程序员文章站 2022-07-15 22:16:43
...

通过该部分的介绍,你会对“封装性”产生怀疑,因为通过反射可以毫无压力的破坏掉这些所谓的封装。
类中的属性必须在本类实例化对象产生产生之后才会分配内存空间,在Class类中存在取得成员的方法,
一是取得全部成员:public Field[] getDeclaredFields()

二是取得指定成员:public Field getDeclaredField(String name)

可以看出,它们的返回值类型都是和Field相关的,观察这个类,其属于java.lang.reflect.Field,该类有两个重要的方法:
1、public Object get(Object obj) 获取此 Field 表示的字段的值
2、
public void set(Object obj, Object value)
`我们可以定义一个类,这个类中存在私有属性,那么在正常情况下,是不可以在类外访问这个属性的,但是可以通过反射来获取该属性。
示例:

package com.andy.entity;

public class Cat {

        private int age;//定义猫的年龄
        private double weight;//定义猫的体重

        public Cat(int age,double weight)
        {
            this.age=age;
            this.weight=weight;
        }

        public Cat() {
           System.out.println("-----这是无参构造函数-----------");
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public double getWeight() {
            return weight;
        }

        public void setWeight(double weight) {
            this.weight = weight;
        }

        @Override
        public String toString() {      
            return "猫的年龄是"+age+"  体重是"+weight;
        }

}

现在在另外一个类中通过反射获取该类的属性,并设置值。
代码如下:

package com.andy.temp;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Temp {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        String fildName1="age";
        String fildName2="weight";
        Class<?>class1=Class.forName("com.andy.entity.Cat");
        try {
            Constructor<?> constructor=class1.getConstructor(int.class,double.class);
            Object cat=constructor.newInstance(2,2.6);//相当于正常情况下的new,会调用构造函数

            Field ageFiled=class1.getDeclaredField("age");//相当于cat.age

            ageFiled.setAccessible(true);//先取消封装
            ageFiled.set(cat, 6);
            Field weightField=class1.getDeclaredField("weight");

            weightField.setAccessible(true);
            weightField.set(cat, 3.6);
            System.out.println(cat);
        } catch (Exception e) {

            e.printStackTrace();
        }


    }
  public static String initcap(String str) {
    return str.substring(0,1).toUpperCase()+str.substring(1).toLowerCase();
 }
}

在java.lang.reflect.Field的上层是继承了java.lang.reflect.AccessibleObject的,在AccessibleObject类中有一个可以取消封装的方法,名为setAccessible,
定义为public void setAccessible(boolean flag),将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
值为 false 则指示反射的对象应该实施 Java 语言访问检查。 注意:这个操作应该在逻辑操作之前进行,否则不成功。