[英]UnsupportedEncodingException is not getting thrown, if we change final property value using reflection
[英]Trying to change the value of a property at runtime using reflection results in NullPointerException
我有一个 class 正在编写单元测试:
import java.io.File;
public class MyLogger {
private final File logFile = new File("default");
public File getLogFile() {
return this.logFile;
}
}
我想从另一个 class 中更改分配给logFile
的值,例如:
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Main {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, Exception {
MyLogger logger = new MyLogger();
System.out.println(logger.getLogFile());
setFinal(MyLogger.class.getDeclaredField("logFile"), new File("changed"));
System.out.println(logger.getLogFile());
}
private static void setFinal(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
}
但我得到以下输出/异常:
default
Exception in thread "main" java.lang.NullPointerException
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:57)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:764)
at Main.setFinal(Main.java:23)
at Main.main(Main.java:12)
问题在于set
方法的第一个参数。 它需要您尝试修改以执行更改的 object 的实例。 现在,您所做的类似于尝试执行null.logFile = newValue
,这显然会失败。
您需要向setFinal
方法添加另一个参数,并将logger
变量传递给它以用作该参数。
public static void main(String[] args) throws NoSuchFieldException, SecurityException, Exception {
MyLogger logger = new MyLogger();
System.out.println(logger.getLogFile());
setFinal(MyLogger.class.getDeclaredField("logFile"), logger, new File("changed"));
System.out.println(logger.getLogFile());
}
private static void setFinal(Field field, Object toModify, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(toModify, newValue);
}
您以错误的方式使用Field.set
方法。 您需要提供必须设置新字段值的object ,在您的代码中它应该是logger
object 但您传递的是null
:
public static void main(String[] args) throws NoSuchFieldException, SecurityException, Exception {
MyLogger logger = new MyLogger();
System.out.println(logger.getLogFile());
setFinal(logger, MyLogger.class.getDeclaredField("logFile"), new File("changed"));
System.out.println(logger.getLogFile());
}
private static void setFinal(MyLogger logger, Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(logger, newValue);
}
这是根据文档中Field.set
的方法签名:
将指定 object 参数上的此字段 object 表示的字段设置为指定的新值。
我可以使用 java.lang.reflect.Method 来做到这一点,检查下面的代码是否有助于解决您的问题。
Method method = MyLogger.getClass().getDeclaredMethod("getLogFile");
method.setAccessible(true);
在 getDeclaredMethod 中,您需要提供完整的方法名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.