3

Why i'm getting false in below statement.

int x = 10;    
System.out.println("X="+x=="X="+x); //false

If i'm right then after evaluation it will look like below statement..

System.out.println("X=10"=="X=10"); //true

And why i'm getting true in this..

final int y = 10;
System.out.println("Y="+y=="Y="+y);
Rahul Kumar
  • 362
  • 1
  • 7
Rahul
  • 65
  • 1
  • 6
  • because that is not how you should compare strings – Naman Jul 10 '20 at 05:40
  • In addition to all answers, maybe this helps you understand: What is `new String("a") == new String("a")` vs `new String("a").equals(new String("a"))`? – knittl Jul 10 '20 at 05:50
  • 1
    Naman i know how to compare string, i'm just asking about the output. – Rahul Jul 10 '20 at 05:52

4 Answers4

3

Strings should be compared using the equals method. == compares identity.

"X=" + x == "X=" + x creates two separate string instances, and while the contents are equal, their identities are not.

"X=10" == "X=10" is true because of string interning. The compiler encounters two string literals with the same contents, and decides that the two occurrences point to the same String object, thus they have the same identity.

"Y=" + y == "Y=" + y is true because y is a constant expression, and the compiler decides that the string and the int can be concatenated at compile time, yielding two equal strings. Effectively, it is as if "Y=10" == "Y=10" were written.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • You mean two different objects at runtime store outside to SCP and pointing to different objects thats why i'm getting false. – Rahul Jul 10 '20 at 05:55
  • I do not know what you mean by "outside to SCP". But `int x = 10` is *not* a constant expression, so the compiler assumes that `x` *could* be changed at runtime. This is why the value of `"X="+x` cannot be determined at compile time, and the compiler is unable to intern those two strings. – MC Emperor Jul 10 '20 at 06:07
2

Let's compare all the approaches

  1. "X="+x=="X="+x is false because those two different instances and == returns false (since == compares address of the objects or strings)

Why ?

Those are not string constants, we will see in below section about constants

  1. "X=10"=="X=10" is true because they are string constants, and compiler creates unique object for same content strings using string intern

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern

  1. "Y="+y=="Y="+y is true because it is constant expression, It is because variable y is declared as final 4.12.4. final Variables and Compile-time constant expressions of type String are always "interned"

A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.

15.28. Constant Expressions

A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

Compile-time constant expressions of type String are always "interned" so as to share unique instances, using the method String.intern.

Examples of constant expressions: Which is similar to you expression "Y="+y

"The integer " + Long.MAX_VALUE + " is mighty big."
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • I'm not sure, that "x" and another "x" are different object references. Literal String instantiations are taken from same String pool, when the value is same. – Giorgi Tsiklauri Jul 10 '20 at 07:01
1

A concatenated String is on compilation put together to a singular String if possible so "X=" + "10" makes "X=10", this also works if the int is final, but if it is a normal variable then this process of course can't happen.

Then the == gets reduced to become an object comparison tool between temporary objects in the comparison and fails for that reason.

Also please don't ever write code like that, as you can see it leads to problems quickly, use braces and the .equals() functions where appropriate.

1

To elaborate on deadpools answer what is most likely happening in the background is code optimisation.

Java will evaluate String s1 == String s2 to true only if it is the same object. because y is declared final the compiler can replace all instances of y with the value it is given

so

final int y = 10;
System.out.println("Y="+y=="Y="+y);

becomes

System.out.println("Y="+10=="Y="+10);

which becomes

String tmp = "Y="+10;
System.out.println(tmp==tmp);

which becomes

System.out.println(true);

However if you do not declare the variable as final then the compiler cannot do this trick as it cannot predict what will happen to y between "Y="+y and "Y="+y.

also doing something like

final int y = x;
System.out.println("Y="+y=="Y="+y);

will cause the(my) compiler to skip this optimisation and then it evaluates to false.

TL;DR

It evaluates to true iff it is the same object, under certain conditions the compiler will optimise the comparison away by doing a pre-calculation.

BevynQ
  • 8,089
  • 4
  • 25
  • 37