Java 从System.in读取的两个相同字符串是否存储在公共内存位置?

Java 从System.in读取的两个相同字符串是否存储在公共内存位置?,java,Java,假设我们有这样的程序: import java.io.*; public class ReadString { public static void main (String[] args) { // prompt the user to enter their name System.out.print("Enter your name: "); // open up standard input BufferedReader

假设我们有这样的程序:

import java.io.*;

public class ReadString {

   public static void main (String[] args) {

      //  prompt the user to enter their name
      System.out.print("Enter your name: ");

      //  open up standard input
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

      String userName = null;
      String userNameCopy = null;

      //  read the username from the command-line; need to use try/catch with the
      //  readLine() method
      try {
         userName = br.readLine();
         System.out.print("Enter your name once again: ");
         userNameCopy = br.readLine();
      } catch (IOException ioe) {
         System.out.println("IO error trying to read your name!");
         System.exit(1);
      }

      System.out.println("Thanks for the name, " + userName);

   }

}  // end of ReadString class
现在,如果用户输入用户名两次,
username
usernamecompy
字符串将具有相同的值。既然字符串是不可变的,Java编译器是否足够聪明,可以只使用一个内存对象和对它的两个引用,或者这种行为只保留给硬编码到程序中的字符串文本


如果答案是“否,编译器将在堆上创建两个单独的对象”。为什么会这样?是因为从池中搜索精确匹配的速度很慢吗?如果是,字符串池不能像某种哈希表或类似的东西一样实现吗?

该池被实现为哈希数据结构。Java将是否执行搜索和共享非文字字符串对象的决定权留给程序员。请参阅String方法。

这与从何处读取字符串无关。事实上,您的输入流实现从从源读取的字节数据创建新字符串。但是,您只能通过查看实现类的源代码来确定这一点。通常,除非类在其文档中明确声明,否则不应假定字符串被类占用。

字符串池的实现由编译器在编译时决定。StringPool由HashMap实现。现在在您的例子中,因为编译器不确定您将向这些变量输入什么字符串,所以现在运行时负责在堆上创建字符串对象。这正是Java处理字符串的方式。但是,如果您想将字符串放入StringPool中,您可以使用
String#intern()

您不应假设任何关于字符串标识的内容您只应假设JLS和/或字符串API文档中指定的关于字符串标识的内容。@PatriciaShanahan即使这些内容也不值得假设IMONo,我不会,我想在检查字符串是否相等时,我永远不应该依赖引用。我问这个问题不是为了“真正的编码”,而是我可能会学到的一些有趣的东西。“如果是的话,字符串池不能像某种哈希表或类似的东西一样实现吗?”哈希表通常仍然比只生成新的
字符串
对象慢。分配非常快而且非常便宜。关于“String.intern()”方法的好提示!我搜索了一下,在这个问题的公认答案中找到了很好的参考: