2011-06-15 42 views
7

我正在研究基本的Java程序,并且发现了与你分享的有趣的事情。 foo()给出输出(s == s1)= false,bar给出(s == s1)= true。在Java中使用不同级联后,为什么在比较字符串时会得到不同的结果?

我想知道为什么会发生这种情况。

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)); 
} 
} 
+1

如果你想比较字符串值,你应该做['equals'](http:// downlo ad.oracle.com/javase/6/docs/api/java/lang/String.html#equals(java.lang.Object)) – asgs 2011-06-15 13:21:47

+0

注意:HTML标记在这里不起作用来格式化代码。 – Jesper 2011-06-15 13:22:27

+0

我不知道这个问题是怎么发生的......;) – Nix 2011-06-15 13:29:14

回答

16

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

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

+0

+1解释*为什么*这是它的方式 – Sorrow 2011-06-15 13:23:53

+0

Thanx哥们.. !! – Chakravyooh 2011-06-15 13:27:30

+0

但是如果我在ompersion之后将bar()中的s1的值更改为..怎么办? – Chakravyooh 2011-06-15 13:38:35

3

bar()的串连环可以在编译时进行,因为它是什么组成的表达,但编译时间常数。虽然在编译时明显知道字符串的长度,但编译器不知道length()返回的是已知值,因此它不会被用作常量。

+0

+1,但是没有人提到使用'.equals()'来比较字符串是否相等? – Mikaveli 2011-06-15 13:27:48

+1

@Mikaveli:我相信@Chakravyooh知道这一点,但这与问题无关。如果你使用'equals()',那么这里有趣的行为就是隐藏的,那里的乐趣在哪里? – 2011-06-15 13:30:06

0

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

2

当你写这样的一行代码:

String s1 = "str" + "4"; 

那么编译器是足够聪明的优化这个到:

String s1 = "str4"; 

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

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

0

如果我需要猜测,我会说java编译器对bar()进行了一些优化。在编译时,很显然“str”+“4”可以被替换为“str4”(因为字符串是不可变的对象)的确是与用于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)); 
0

您应该尝试使用String类的intern方法来玩。 Java保留了所有不同字符串存储在其中的字典。当您创建可在编译时评估的字符串对象时,Java会在其字典中进行搜索。如果它找到字符串,它只存储对此字符串的引用(实际上由intern方法返回)。

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

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

在第一种情况下s.length()将返回类型INT的值,在第二情况下的类型是字符串 即使数量是4在这两种情况下,但类型不一样:)

相关问题