- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
下面是 String.intern() 方法的 Javadoc 注释:
*返回字符串对象的规范表示。
一个字符串池,最初是空的,由 String 类私下维护。
当调用 intern 方法时,如果池中已经包含等于此 String 对象的字符串(由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中并返回对此 String 对象的引用。
因此对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 为真。
所有文字字符串和字符串值常量表达式都被驻留。字符串文字在 The Java™ Language Specification 的第 3.10.5 节中定义。
但我认为从 jdk-8u102 开始发生了一些变化。
检查下面的例子:
public class Test1 {
public static void main(String[] args) {
String s1 = new String(new char[]{'J', 'a', 'v', 'a'});
String s2 = s1.intern();
System.out.println(s1 == s2);
}
}
如果您在 JDK 7u80(JDK 7 的最新稳定版本)和 JDK 8 至 8u101 中运行上述程序,则输出为:
正确
但如果您在 JDK 8u102 及 JDK 9 和 JDK 10 中运行上述程序,则输出为:
假
为什么从 JDK 8u102 开始,intern() 方法开始表现不同?
我检查了发行说明和 Javadoc 注释,但找不到任何与 JDK 8u102 中的 intern() 方法相关的更改。
我检查了博客和其他网站,但没有成功。
但是当我尝试使用其他字符串时,输出没有任何变化:
public class Test2 {
public static void main(String[] args) {
String s3 = new String(new char[]{'U', 'd', 'a', 'y', 'a', 'n'});
String s4 = s3.intern();
System.out.println(s3 == s4);
}
}
以上程序在 JDK 7、JDK 8、JDK 9 和 JDK 10 中始终打印 true。
只有在加载 Test1 类之前“Java”被字符串池表引用时,此行为才有可能。
s1 引用 HEAP 上的字符串对象“Java”,s1.intern() 返回字符串池对象的引用(因为“Java”已被字符串池引用)。
这就是 s1 == s2 返回 false 的原因。
但是当加载 Test2 类时,字符串池表不引用“Udayan”。
s3 引用 HEAP 上的字符串对象“Udayan”,s3.intern() 将 s3 引用的字符串对象添加到字符串池并返回相同的引用。这意味着 s3 和 s4 指的是同一个对象。
这就是 s3 == s4 返回 true 的原因。
如果我的观察是正确的,那么这意味着字符串池最初不是空的。
字符串池最初包含“Java”、“java”、“Oracle”等字符串对象。
任何人都可以证实这一点吗?
最佳答案
这取决于你认为什么是“最初”。
当 JVM 启动时,String Pool 是空的。然而,当各种基本的 JDK 类在您的 Test1
类被加载之前被加载和初始化时,其中一些将 String
添加到字符串池中也就不足为奇了。 “Java”必须是这些 String
之一。
并且 JLS 中没有任何内容阻止 Java 开发人员在较新的 JDK 版本中的类初始化中引入新的 String
文字。因此,您注意到 JDK 7 和 JDK 8 之间的差异并不奇怪。
关于java - 正如 String.intern() 方法的 Javadoc 中提到的那样,String Pool 最初真的是空的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50000370/
如果您想使用 String.Concat() 连接 5 个或更多字符串,则它会使用 Concat(String[])。 为什么不一直使用 Concat(String[]) 而不再需要 Concat(S
今天在使用 String 时,我遇到了一种我以前不知道的行为。我无法理解内部发生的事情。 public String returnVal(){ return "5";
似乎在我所看到的任何地方,都有一些过时的版本,这些版本不再起作用。 我的问题似乎很简单。我有一个Java类,它映射到derby数据库。我正在使用注释,并且已经成功地在数据库中创建了所有其他表,但是在这
一、string::size_type() 在C++标准库类型 string ,在调用size函数求解string 对象时,返回值为size_type类型,一种类似于unsigned类型的int 数据
我正在尝试将数据保存到我的 plist 文件中,其中包含字符串数组的定义。我的plist - enter image description here 我将数据写入 plist 的代码是 -- let
我有一个带有键/值对的 JavaScript 对象,其中值是字符串数组: var errors = { "Message": ["Error #1", "Error #2"], "Em
例如,为了使用相同的函数迭代 List 和 List> ,我可以编写如下内容: import java.util.*; public class Test{ public static voi
第一个Dictionary就像 Dictionary ParentDict = new Dictionary(); ParentDict.Add("A_1", "1")
这是我的 jsp 文件: 我遇到了错误 The method replace(String, String, String) in the type Functions is not appl
我需要一些帮助。我有一个方法应该输出一个包含列表内容的 txt 文件(每行中的每个项目)。列表项是字符串数组。问题是,当我调用 string.Join 时,它返回文字字符串 "System.Strin
一位同事告诉我,使用以下方法: string url = "SomeURL"; string ext = "SomeExt"; string sub = "SomeSub"; string s
给定类: public class CategoryValuePair { String category; String value; } 还有一个方法: public
我正在尝试合并 Stream>>对象与所有 Streams 中的键一起映射到单个映射中. 例如, final Map someObject; final List>> list = someObjec
在这里使用 IDictionary 的值(value)是什么? 最佳答案 使用接口(interface)的值(value)始终相同:切换到另一个后端实现时,您不必更改客户端代码。 请考虑稍后分析您的代
我可以知道这两个字典声明之间的区别吗? var places = [String: String]() var places = [Dictionary()] 为什么当我尝试以这种方式附加声明时,只有
在 .NET 4.0 及更高版本中存在 string.IsNullOrWhiteSpace(string) 时,在检查字符串时使用 string.IsNullOrEmpty(string) 是否被视为
这个名字背后的原因是什么? SS64在 PowerShell 中解释此处的字符串如下: A here string is a single-quoted or double-quoted string
我打算离开 this 文章,尝试编写一个接受字符串和 &str 的函数,但我遇到了问题。我有以下功能: pub fn new(t_num: S) -> BigNum where S: Into {
我有一个结构为 [String: [String: String]] 的多维数组。我可以使用 for 循环到达 [String: String] 位,但我不知道如何访问主键(这个位 [String:
我正在尝试使用 sarama(管理员模式)创建主题。没有 ConfigEntries 工作正常。但我需要定义一些配置。 我设置了主题配置(这里发生了错误): tConfigs := map[s
我是一名优秀的程序员,十分优秀!