我越了解 java.lang.reflect.AccessibleObject.setAccessible
的威力,我就越惊讶于它的能力。这是根据我对这个问题的回答改编的(使用反射来更改单元测试的静态 final File.披露字符)。
import java.lang.reflect.*;
public class EverythingIsTrue {
static void setFinalStatic(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);
}
public static void main(String args[]) throws Exception {
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
}
}
你可以做一些非常离谱的事情:
public class UltimateAnswerToEverything {
static Integer[] ultimateAnswer() {
Integer[] ret = new Integer[256];
java.util.Arrays.fill(ret, 42);
return ret;
}
public static void main(String args[]) throws Exception {
EverythingIsTrue.setFinalStatic(
Class.forName("java.lang.Integer$IntegerCache")
.getDeclaredField("cache"),
ultimateAnswer()
);
System.out.format("6 * 9 = %d", 6 * 9); // "6 * 9 = 42"
}
}
据推测,API 设计人员已经意识到 setAccessible
的可滥用性,但是他们必须承认 setAccessible
有合法的用途来提供它。所以我的问题是:
setAccessible
的真正合法用途是什么?
setAccessible
仅限于合法用途?
SecurityManager
吗?
SecurityManager
的配置如何,我都可以编写 setAccessible
防护类吗?
我想还有一个更重要的问题: 我需要担心这个吗?
我的课堂上没有任何隐私可以强制执行。这项单例模式(先不考虑其是非曲直)现在已无法执行。正如我上面的片段所显示的,即使是一些关于 Java 基本原理如何工作的基本假设也远远不能得到保证。
这些问题不是真的吗?
好的,我刚刚确认: 由于 setAccessible
,Java 字符串是 没有不可变的。
import java.lang.reflect.*;
public class MutableStrings {
static void mutate(String s) throws Exception {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set(s, s.toUpperCase().toCharArray());
}
public static void main(String args[]) throws Exception {
final String s = "Hello world!";
System.out.println(s); // "Hello world!"
mutate(s);
System.out.println(s); // "HELLO WORLD!"
}
}
只有我一个人认为这是个大问题吗?