此源代码打开了一些有趣的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");第一行检索Reflected Class
Object,第二行检索a
Field,它代表类的
value字段
String。
value.setAccessible(true)指示反射的类对象在使用时应禁止Java语言访问检查。(参考)
正在讨论的下一行是
value.set("Hello World", value.get("G'Day Mate."));如果我们深入研究.set()文档,我们可以看到我们正在调用的
set(ObjectaObject,Object value)版本
set。
value.get("G'Day Mate.")返回"G'DayMate."的
value字段值实际上是
char[]。并通过调用
set将该
"HelloWorld"对象的value字段的值替换为
"G'Day Mate."object的value字段。
static解释了该块的代码。
让我们潜入主要功能。很简单 它应该输出
Hello, world。但它正在输出
G'Day Mate。为什么?因为
Hello,world我们在
static初始化程序中创建的String对象与
Hello,world我们在main函数中使用的对象相同。再次与JLS协商将为您提供帮助
而且,字符串文字总是引用类String的相同实例。这是因为使用方法String.intern,对“字符串文字”(或更一般地说,是作为常量表达式的值的字符串(第15.28节))进行了“插入”,以便共享唯一的实例。
因此,由于我们已经将
Hello,worldobject的值更改为,因此它显示了不同的值
G'Day, Mate。
但是,如果您
new String("Helloworld")在main函数中使用它,它将直接创建一个新实例,String而不是检入其池中。因此
Helloworldmain函数将不同于
Hello world我们已更改其值的静态初始值设定项。



