为什么在Java中使用不同的连接后比较字符串时会得到不同的结果?

时间:2011-06-15 13:18:56

标签: java

我正在研究基本的java程序,我发现了与你分享的有趣的事情。 foo()给出输出(s == s1)= false,bar给出(s == s1)= true。

我想知道为什么会这样。

public class StringTest
{
  public static void main(String[] args){
    foo();
    bar();
  }
  public static void foo(){
    String s = "str4";
    String s1 = "str" + s.length();
    System.out.println("(s==s1) = " + (s1==s));
  }
  public static void bar(){
    String s = "str4";
    String s1 = "str" + "4";
    System.out.println("(s==s1) = " + (s1==s));
 }
}

7 个答案:

答案 0 :(得分:16)

在后一种情况下,编译器会优化字符串连接。由于这可以在编译时完成,因此它们都引用相同的常量字符串对象。

在前一种情况下,length()调用在编译期间无法优化。在运行时,会创建一个新的字符串对象,该字符串对象与字符串常量(但等于它)

不同

答案 1 :(得分:3)

bar()中的字符串连接可以在编译时完成,因为它是一个只由编译时常量组成的表达式。虽然字符串s的长度在编译时显然是已知的,但编译器不知道length()返回该已知值,因此它不会用作常量。

答案 2 :(得分:2)

当您编写如下代码行时:

String s1 = "str" + "4";

然后编译器足够聪明,可以将其优化为:

String s1 = "str4";

Java中的文字字符串在字符串池中管理。如果您有两个具有相同内容的文字字符串(例如第二个示例中的ss1),则只会创建一个String对象,这两个对象将由两个共享变量

Java中的==运算符检查两个变量是否引用同一个对象。由于第二个示例中只有一个String对象,s == s1将为true

答案 3 :(得分:2)

  • String s1 = "str" + s.length();
  • String s1 = "str" + "4";

在第一种情况下,s.length()将返回类型 int 的值,在第二种情况下,类型为 String 即使两个案例中的数字都是4,但类型不一样:)

答案 4 :(得分:0)

这可能与foo()可能在s.length()(。toString())中创建一个新的String实例这一事实有关,其中bar()只是连接一个常量。我不知道它的细节,但我的直觉告诉我这个方向

答案 5 :(得分:0)

如果我需要猜测我会说java编译器对bar()执行一些优化。在编译时,很明显“str”+“4”可以替换为“str4”,因为Strings是不可变对象,它实际上与用于s初始化的“str4”-String完全相同。

在foo()中,优化不是直接向前发展。通常,不能很容易地预测值s1变量(实际上这个例子非常直接)。所以java编译器会为s和s1生成两个不同的变量。

“==”运算符不会比较字符串的值!它检查这些是否是相同的对象。要比较字符串的值,请使用“equals”方法,如下所示:

String s = "str4";
String s1 = "str" + s.length();
System.out.println("(s==s1) = " + (s1.equals(s2));

答案 6 :(得分:0)

您应该尝试使用String类的实习方法。 Java保存了类似于字典的内容,其中存储了所有不同的字当您创建可在编译时计算的字符串对象时,Java会在其字典中搜索它。如果它找到了字符串,它只存储对该字符串的引用(实际上是由intern方法返回的)。

你应该注意到: "str4" == ("str" + "str4".length())返回false,但是 "str4" == ("str" + "str4".length()).intern()返回true,因为唯一的“包装器”是另一个对象。