转载请注明出处:https://blog.youkuaiyun.com/jiyisuifeng222/article/details/117670430
本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 情花打雪 即可关注,每个工作日都有文章更新。
本篇文章主要讲解Java反射中Field字段对象的相关操作:
-
访问字段(Field)对象的方法汇总
-
获取字段(Field)对象中的值
-
设置字段(Filed)对象中的值
-
区别和注意点
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来访问Student的name字段,编译器会根据public、protected和private决定是否允许访问字段,这样就达到了数据封装的目的。
而反射是一种非常规的用法,使用反射,首先代码非常繁琐,其次,它更多地是给工具或者底层框架来使用,目的是在不知道目标实例任何信息的情况下,获取特定字段的值。
此外,setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)。例如,某个SecurityManager可能不允许对java和javax开头的package的类调用 setAccessible(true),这样可以保证JVM核心库的安全。
3.设置字段中的值,即更新
set与get类似
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);避开检查。
关注我的技术公众号,每天都有优质技术文章推送。
微信扫一扫下方二维码即可关注:
本文详述Java反射中Field对象的操作,包括访问、获取和设置字段值,以及getFields()与getDeclaredFields()的区别,强调反射在数据封装中的特殊性及安全性问题。

1609

被折叠的 条评论
为什么被折叠?



