3

假设我们有这样的程序:

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字符串userNameCopy将具有相同的值。由于字符串是不可变的,Java 编译器是否足够聪明,可以只使用一个内存对象和两个对它的引用,还是这种行为只保留给硬编码到程序中的字符串文字?

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

4

3 回答 3

6

池被实现为散列数据结构。Java 将是否进行搜索和共享非文字字符串对象的决定留给程序员。请参阅字符串方法intern()

于 2013-04-01T17:44:08.557 回答
3

这与您从哪里读取字符串无关。事实上,您的输入流实现从从源读取的字节数据创建新字符串。但是,您只能通过查看实现类的源代码才能确定这一点。一般来说,你不应该假设字符串被一个类所保留,除非它在其文档中明确说明。

于 2013-04-01T17:46:06.853 回答
1

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

于 2013-04-01T18:07:42.597 回答