private
看一个最常见的例子
public class Pojo {
private StringBuilder name = new StringBuilder("john");
public void printName() {
System.out.println(name);
}
}
使用反射修改private修饰符的变量name
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Pojo p = new Pojo();
// 查看被修改之前的值
p.printName();
// 反射获取字段, name成员变量
Field nameField = p.getClass().getDeclaredField("name");
// 由于name成员变量是private, 所以需要进行访问权限设定
nameField.setAccessible(true);
// 使用反射进行赋值
nameField.set(p, new StringBuilder("111"));
// 打印查看被修改后的值
p.printName();
}
}
输出
john
111
static
static修饰的一个name变量
public class Pojo {
private static StringBuilder name = new StringBuilder("john");
public void printInfo() {
System.out.println(name);
}
}
使用反射修改static修饰符的变量name
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Pojo p = new Pojo();
// 查看被修改之前的值
p.printInfo();
// 反射获取字段, name成员变量
Field nameField = p.getClass().getDeclaredField("name");
// 进行访问权限设定
nameField.setAccessible(true);
// 使用反射进行赋值
nameField.set(p,new StringBuilder("kate"));
// 打印查看被修改后的值
p.printInfo();
}
}
输出
john
kate
final
刚才使用反射成功修改了private修饰的变量, 那么如果是final修饰的变量那么还能否使用反射来进行修改呢?这时候就需要分情况了。
final字段能否修改,有且取决于字段是直接赋值还是间接赋值(编译时赋值和运行时赋值的区别)。直接赋值是指在创建字段时就对字段进行赋值,并且值为JAVA的8种基础数据类型或者String类型,而且值不能是经过逻辑判断产生的,其他情况均为间接赋值。
直接赋值
定义直接赋值的final修饰符属性
public class Pojo {
private final String name = "john";
public final int age = 20-2;
public void printInfo() {
System.out.println(name+" "+age);
}
}
尝试通过反射修改属性失败
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Pojo p = new Pojo();
// 查看被修改之前的值
p.printInfo();
// 反射获取字段, name和age成员变量
Field nameField = p.getClass().getDeclaredField("name");
Field ageField = p.getClass().getDeclaredField("age");
// 进行访问权限设定
nameField.setAccessible(true);
ageField.setAccessible(true);
// 使用反射进行赋值
nameField.set(p,"kate");
ageField.set(p,88);
// 打印查看被修改后的值
p.printInfo();
}
}
输出
john 18
john 18
间接赋值
下面这些是间接赋值的final修饰符属性
public class Pojo {
// new生成的对象赋值
private final StringBuilder sex = new StringBuilder("male");
// 经过逻辑判断产生的变量赋值
public final int age = (null!=null?18:18);
// 通过构造函数进行赋值
private final String name;
public Pojo(){
name = "john";
}
public void printInfo() {
System.out.println(name+" "+age+" "+sex);
}
}
尝试通过反射进行修改其属性
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Pojo p = new Pojo();
// 查看被修改之前的值
p.printInfo();
// 反射获取字段, name和age和sex成员变量
Field nameField = p.getClass().getDeclaredField("name");
Field ageField = p.getClass().getDeclaredField("age");
Field sexField = p.getClass().getDeclaredField("sex");
// 进行访问权限设定
nameField.setAccessible(true);
ageField.setAccessible(true);
sexField.setAccessible(true);
// 使用反射进行赋值
nameField.set(p,"kate");
ageField.set(p,88);
sexField.set(p, new StringBuilder("female"));
// 打印查看被修改后的值
p.printInfo();
}
}
输出
john 18 male
kate 88 female
static + final
使用static final修饰符的name属性,并且是间接赋值
public class Pojo {
static final StringBuilder name = new StringBuilder("john");
public void printInfo() {
System.out.println(name);
}
}
通过反射去修改name属性
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Pojo p = new Pojo();
// 查看被修改之前的值
p.printInfo();
// 反射获取字段, name成员变量
Field nameField = p.getClass().getDeclaredField("name");
// 进行访问权限设定
nameField.setAccessible(true);
// 再通过反射, 把nameField的final修饰符去掉
Field modifiers = nameField.getClass().getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);
// 使用反射进行赋值
nameField.set(p,new StringBuilder("kate"));
// 最后别忘了再把final修饰符加回来
modifiers.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);
// 打印查看被修改后的值
p.printInfo();
}
}
输出
john
kate