此源输出G'Day Mate.
这是怎么回事?
public static void main(String args[]) {
System.out.println("Hello World");
}
static {
try {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set("Hello World", value.get("G'Day Mate."));
} catch (Exception e) {
throw new AssertionError(e);
}
}
如果我们将主要功能更改"Hello World"
为new String("Hello World")
:
System.out.println(new String("Hello World"));
它输出Hello world
。
实际发生了什么?
此源代码打开了一些有趣的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(Object aObject,Object value)
版本set
。value.get("G'Day Mate.")
返回"G'Day Mate."
的value
字段值实际上是char[]
。并通过调用set
将该"Hello World"
对象的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,world
object的值更改为,因此它显示了不同的值G'Day, Mate
。
但是,如果您new String("Hello world")
在main函数中使用它,它将直接创建一个新实例,String
而不是检入其池中。因此Hello world
main函数将不同于Hello world
我们已更改其值的静态初始值设定项。
这个问题不难,我已经用自己的方法解决了,但我想听听你的意见,也许有什么方法可以让这成为一个改进的选择?Java 8-11。
问题内容: 我正在尝试找到这个问题的第三种解决方案。 我不明白为什么这个不打印。 当然,由于使用字符串实习,被修改的实例与?方法中使用的实例完全相同。 我想念什么? 编辑 @yshavit有趣的一点是,如果您添加该行 在之前,输出为 问题答案: 可以说这是HotSpot JVM错误。 问题在于字符串字面量的内部机制 。 在常量池解析期间,将懒惰地创建字符串文字的实例。 最初,字符串常量在常量池中由
主要内容:使用连接运算符“+”,使用 concat() 方法,连接其他类型数据对于已经定义的字符串,可以对其进行各种操作。连接多个字符串是字符串操作中最简单的一种。通过字符串连接,可以将两个或多个字符串、字符、整数和浮点数等类型的数据连成一个更大的字符串。 String 字符串虽然是不可变字符串,但也可以进行拼接只是会产生一个新的对象。String 字符串拼接可以使用“+”运算符或 String 的 concat(String str) 方法。 “+”运算符优势是可以连接任
问题内容: 我试图理解字符串比较与字符串比较的输出。需要明确的是,我拥有使用==和equals比较两个字符串的类。我试图将==和equals()的输出合并为字符串。equals()的输出会连续显示,但==的输出不会 连续显示。使用Java的装箱功能,将与字符串连接的布尔值联系起来。equals和==都返回布尔值。那么为什么会有这种差异呢?有人可以解释吗? 输出 更新:答案 如果不使用s1 == s
本文向大家介绍Java中拆分和拼接字符串,包括了Java中拆分和拼接字符串的使用技巧和注意事项,需要的朋友参考一下 要在Java中拆分和连接字符串,请使用以下示例中的split和join方法- 示例 输出结果 一个名为Demo的类包含主函数。这里定义了一个字符串对象,并根据直到最后一个单词的值对其进行分割。循环遍历一个for循环,并根据该值分割字符串。同样,使用join函数连接字符串。相关消息显示
如果你使用过python,你会发现字符串和int/float/double便捷的拼接方式;但如果你使用C++,可能你每次需要的时候搜索一下才能知道。本文提供两种简单的方式来完成这个功能。 std::to_string() 通过std::to_string()将数字类型转换成std::string类型,从而可以直接使用+完成字符串的拼接。 # include <iostream> int main