Java反射第二部分:访问字段(Field)、获取字段(Field)、更新字段(Field)

本文详述Java反射中Field对象的操作,包括访问、获取和设置字段值,以及getFields()与getDeclaredFields()的区别,强调反射在数据封装中的特殊性及安全性问题。

转载请注明出处:https://blog.youkuaiyun.com/jiyisuifeng222/article/details/117670430

本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 情花打雪 即可关注,每个工作日都有文章更新。

本篇文章主要讲解Java反射中Field字段对象的相关操作:

  1. 访问字段(Field)对象的方法汇总

  2. 获取字段(Field)对象中的值

  3. 设置字段(Filed)对象中的值

  4. 区别和注意点

1.访问Field的方法汇总

以下四种方法在Class类可以返回关于字段的 Field 对象。

Field[] getFields()   // 返回所有可访问的公共字段,在类中声明或继承自父类。

Field[] getDeclaredFields()  //获取当前类的所有field(不包括父类)

Field getField(String name)  //根据字段名获取某个public的field(包括父类)

Field getDeclaredField(String name)  //根据字段名获取当前类的某个field(不包括父类)

Field是一个类对于我们想研究的某个字段(比如自定义的Student类的字段id),对应着Filed类的一个对象。

  • Filed类中定义的主要属性如下:
public final class Field extends AccessibleObject implements Member {
    private Class<?>            clazz;//
    private int                 slot;
    private String              name;
    private Class<?>            type;//
    private int                 modifiers;//修饰符
    private transient String    signature;
    private transient FieldRepository genericInfo;
    private byte[]              annotations;
    private FieldAccessor fieldAccessor;
    private FieldAccessor overrideFieldAccessor;
    ......
    
    @CallerSensitive
    // Android-changed: get*(Object) implemented natively.
    @FastNative
    public native Object get(Object obj)
        throws IllegalArgumentException, IllegalAccessException;

    @CallerSensitive
    // Android-changed: set*(Object, ...) implemented natively.
    @FastNative
    public native void set(Object obj, Object value)
        throws IllegalArgumentException, IllegalAccessException;
    ......
}
class Student {
    public int id;
    private int studentName;
    public int score;
}
  • Filed的部分访问方法:
 Field field=Student.class.getField("score");
 System.out.println(field.getClass());//class java.lang.reflect.Field
 System.out.println(field.getName());//score
 System.out.println(field.getType());//int
 int modifier=field.getModifiers();
 System.out.println(Modifier.isFinal(modifier));//false
 System.out.println(Modifier.isPublic(modifier));//true

2.获取Field中的值

  • 获取公有字段的值
  • 获取私有字段的值
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class AccessTypeTest {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Student student=new Student("记忆随风");
        Field f1=Student.class.getField("name");
        System.out.println(f1.get(student));//获取Field对象中的public字段的值
        Field f2=Student.class.getDeclaredField("grade");
        f2.setAccessible(true);//①不加这行代码   ②加这行
        System.out.println(f2.get(student));//获取Field对象中的私有字段的值  
        // ①IllegalAccessException    ② 0
    }
}


class Student  {
    public String name;
    private int grade;
    public Student(String name) {
        this.name = name;
    }
}

 

可能有人回问:如果使用反射可以获取private字段的值,那么类的封装还有什么意义?

答案是:正常情况下,我们总是通过student.name来访问Studentname字段,编译器会根据publicprotectedprivate决定是否允许访问字段,这样就达到了数据封装的目的。

而反射是一种非常规的用法,使用反射,首先代码非常繁琐,其次,它更多地是给工具或者底层框架来使用,目的是在不知道目标实例任何信息的情况下,获取特定字段的值。

此外,setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)。例如,某个SecurityManager可能不允许对javajavax开头的package的类调用       setAccessible(true),这样可以保证JVM核心库的安全。

3.设置字段中的值,即更新

setget类似

f2.setAccessible(true);
f2.set(student,10000);
System.out.println(f2.get(student));//10000

4.区别和注意点

getFields()与getDeclaredFields()区别

1.getFields()返回所有可访问公共字段在类中声明继承自父类

2.getDeclaredFields()获取当前类的所有field不包括父类)。但是可以是public或者private修饰的。注意:访问private修饰字段,需要设置field.setAccessible(true);避开检查

 

关注我的技术公众号,每天都有优质技术文章推送。

微信扫一扫下方二维码即可关注:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值