开发者

Why do I get different results when comparing strings after using different concatenation in Java?

i was working on the basic java program and i found verry funny thing which i am sharing with you. foo() gives output (s==s1) = false and bar gives (s==s1) = true.

I want to know why this happens.

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


In the latter case, the compiler optimizes the string concatenation. As this can be done at compile time, both reference the same constant string object.

In the former case, the length() call can't be optimized during compile time. At runtime, a new string object is created, which is not identical to the string constant (but equal to it)


The string catenation in bar() can be done at compile time, because it's an expression composed of nothing but compile-time constants. Although the length of the String s is obviously known at compile time, the compiler doesn't know that length() returns that known value, so it won't be used as a constant.


When you write a line of code like this:

String s1 = "str" + "4";

then the compiler is smart enough to optimize this to:

String s1 = "str4";

Literal strings in Java are managed in a string pool. When you have two literal strings that have the same content (such as s and s1 in your second example), then just one String object will be created which will be shared by the two variables.

The == operator in Java checks if two variables refer to the same object. Since there is only one String object in the second example, s == s1 will be true.


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

In first case s.length() will return a value of type int, In second case The type is String Even though the number is 4 in both the cases but types are not the same :)


It probably has to do with the fact that foo() is probably creating an new String instance in s.length()(.toString()), where as bar() is just concatenating a constant. I don't know the nitty gritty of it, but my gut tells me it in that direction


If I needed to guess I would say that the java compiler performs some optimization onto bar(). At compiletime it is clear that "str" + "4" can be replaced by "str4" which (since Strings are immutable objects) is indeed the very same object as "str4"-String used for the s-initialization.

Within foo() the optimization is not that streight forward. In general the value s1-variable cannot be predicted very easily (indeed this example is quite streight forward). So the java compiler will produce two different variables for s and s1.

The "==" operator does not compare the value of the Strings! It checks whether these are the same Objects. To compare the values of the Strings use the "equals" method like this:

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


You should try playing with intern method of String class. Java keeps something like dictionary where all different strings are stored. When you create a string object which can be evaluated at compile time, Java searches it in its dictionary. If it founds the string, it stores only a reference to this string (which is actually returned by intern method).

You should notice that: "str4" == ("str" + "str4".length()) returns false, but "str4" == ("str" + "str4".length()).intern() returns true, because the only "wrapper" is a different object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜