这个源代码开辟了一些有趣的java技术。让我们逐一检查。
首先,我们需要了解代码的流程。代码的哪一部分将首先执行?
静态初始化块。为什么?让我们参考 Java 语言规范 (12.4):
类的初始化包括执行其静态初始值设定项和类中声明的静态字段(类变量)的初始值设定项。
它何时发生?再次来自 JLS (12.4.1) :
T 是一个类,调用由 T 声明的静态方法。
因此,我们可以得出结论,静态初始化器将首先在main方法之前执行。
现在,这两条线使用反射:
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
为了简单起见,我们可以将拳头线分成两行:
Class<String> c = String.class;
Field value = c.getDeclaredField("value");
第一行检索反射的类对象,第二行检索表示类的字段的 a。Field
value
String
value.setAccessible(true)
指示反射的类对象在使用时应禁止 Java 语言访问检查。(参考资料)。
下一行是
value.set("Hello World", value.get("G'Day Mate."));
如果我们深入研究 .set() 文档,我们可以看到我们正在调用 的版本。 返回 的字段的值,该值实际上是一个 。并且通过它的调用,将对象的值字段的值替换为对象的值字段。set(Object aObject,Object value)
set
value.get("G'Day Mate.")
"G'Day Mate."
value
char[]
set
"Hello World"
"G'Day Mate."
块的代码已解释。static
让我们深入了解主要功能。这很简单。它应该输出 。但它正在输出 。为什么?因为我们在初始值设定项中创建的 String 对象与我们在 main 函数中使用的对象相同。再次咨询JLS将阐明这一点Hello, world
G'Day Mate
Hello, world
static
Hello, world
此外,字符串文本始终引用类 String 的同一实例。这是因为字符串文本 (或者更一般地说,作为常量表达式的值的字符串 (§15.28) ) 被“暂存”,以便使用 String.intern 方法共享唯一实例。
这个答案可以帮助你更简洁地理解事实。
因此,它显示不同的值,因为我们已经将对象的值更改为 。Hello,world
G'Day, Mate
但是,如果您在main函数中使用,它将直接创建一个新的实例,而不是签入其池。因此,main 函数将不同于静态初始值设定项,我们已更改其值。new String("Hello world")
String
Hello world
Hello world