Java反射的Field
Java 反射获取 Field 的 4 种方法总结
1.getField():只能获取public,包括继承父类的
2.getDeclaredFiled():可以获取类声明的任何字段,但是不包括父类继承的
3.getFields():返回所有public字段,包括父类继承的
4.getDeclaredFields:返回声明的所有字段,不包括从父类继承的
常见两个异常
NoSuchFieldException
IllegalAccessException
权限与setAccessible(true)

示例
对于User类:
public的字段location, private字段id, default字段age, protected字段salary;
package reflect.bean;/*** @author * @version 1.0* @description: TODO* @date 2025/7/30 11:40*/
public class User {public String location;private String id;int age;String name;protected double salary;public User() {}public User(int age, String name) {this.age = age;this.name = name;}public User(String id, int age, String name) {this.id = id;this.age = age;this.name = name;}private int getNum(){return 1;}public int getA(){return 3;}int getB(){return 4;}public static void utils(){System.out.println("test");}@Overridepublic String toString() {return "User{" +"location='" + location + '\'' +", id='" + id + '\'' +", age=" + age +", name='" + name + '\'' +", salary=" + salary +'}';}
}
测试getField方法
访问public字段可以,其他字段不行,会报错
// 只能获取 public 修饰的字段(包括从父类继承的)@Testpublic void testGetField() throws NoSuchFieldException{Field location = User.class.getField("location");System.out.println(location);// Field age = User.class.getField("age");
// System.out.println(age);}
测试getDeclaredField
// 可以获取类中声明的任何字段(包括 private、protected、public)//不能获取从父类继承的字段@Testpublic void testGetDeclaredField()throws NoSuchFieldException{Field age = User.class.getDeclaredField("age");System.out.println(age);}
测试getFields()
// 返回所有 public 字段(包括从父类继承的)@Testpublic void testGetFields() throws NoSuchFieldException{Field[] fields = User.class.getFields();for(Field field:fields){System.out.println(field);}}
测试getDeclaredFields()
// 返回类中声明的所有字段(包括 private、protected、public)
//
// 不包含从父类继承的字段@Testpublic void testGetDeclaredFields() throws NoSuchFieldException{Field[] declaredFields = User.class.getDeclaredFields();for(Field field:declaredFields){System.out.println(field);}}
测试setAccessible
如果在User同一个包下:访问default和protected字段都行
package reflect.bean;import java.lang.reflect.Field;/*** @author * @version 1.0* @description: TODO* @date 2025/8/4 20:11*/
public class Test {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {Field location = User.class.getField("location");User user = new User();location.set(user,"巢湖市区");System.out.println(user);Field id = User.class.getDeclaredField("id");id.setAccessible(true);id.set(user,"222");System.out.println(user);Field age = User.class.getDeclaredField("age");age.set(user,11);System.out.println(user);Field salary = User.class.getDeclaredField("salary");salary.set(user,19992.2);System.out.println(user);}
}
如果不在同一个包下,则对于default必须setAccessible()
对于public字段自然都不需要setAccessible,对于private字段都需要setAccessible.
那么对于protected呢?在同一个包下自然不需要setAccessible,而对于其子类是什么情况?
package reflect.test;import reflect.bean.User;import java.lang.reflect.Field;/*** @author* @version 1.0* @description: TODO* @date 2025/8/4 20:35*/
public class SubTest extends User {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {Class<User> userClass = User.class;Field salary1 = User.class.getDeclaredField("salary");salary1.set(userClass,199.3);System.out.println(userClass);}
}
发现报错:
Exception in thread "main" java.lang.IllegalAccessException: class reflect.test.SubTest cannot access a member of class reflect.bean.User with modifiers "protected"at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)at java.base/java.lang.reflect.Field.checkAccess(Field.java:1102)at java.base/java.lang.reflect.Field.set(Field.java:797)at reflect.test.SubTest.main(SubTest.java:17)
子类可以通过 this 或 super 直接访问继承的 protected 字段(即使跨包)。
public class SubTest extends User {public void modifySalary() {this.salary = 1000; // 允许(通过子类实例访问)super.salary = 1000; // 允许(通过 super 访问)}
}
禁止访问:子类不能通过父类实例访问 protected 字段(跨包时):
User user = new User();
user.salary = 1000; // 编译错误!跨包时不允许
(2) 反射访问(Field.set())
默认禁止:反射 API 对访问控制的检查比普通代码更严格,即使子类通过反射访问父类的 protected 字段,也会抛出 IllegalAccessException。
必须要显式调用 setAccessible(true) 绕过检查
访问对象属性和修改对象属性
@Testpublic void testOperation2() throws NoSuchFieldException, IllegalAccessException {User user = new User("zx", 22, "222");Field age = User.class.getDeclaredField("age");age.setAccessible(true);Object o = age.get(user);System.out.println(o);}
@Testpublic void testOperation() throws NoSuchFieldException, IllegalAccessException {Field location = User.class.getField("location");User user = new User();location.set(user,"beijing");System.out.println(user);Field id = User.class.getDeclaredField("id");id.setAccessible(true);id.set(user,"222");System.out.println(user);Field age = User.class.getDeclaredField("age");age.setAccessible(true);age.set(user,11);System.out.println(user);Field salary = User.class.getDeclaredField("salary");salary.set(user,19992.1);System.out.println(user);}
