-2

Situation: Girlfriend's Java teacher says the following statements are equivalent. At the same time, a Java book recommends the latter form.

String a = new String("Hi");

String b = "Hi";

Then a.equals(b), and the world is fine.

However, my Java text and C knowledge gravely inform me that since a==b as well as a.equals(b), if a is changed (Not likely in a String, but what if it gets mutated anyhow, as it is probably possible to pass the address somehow that even the JVM won't stop) then b will also be changed. As such, it could be dangerous to assume that b.equals("Hi").

Any insight? Is the declaration for b really safe, or just a lot lighter on the RAM?

I am not asking about what the difference is. I know that b probably references the same object created in a.

Aviator45003
  • 253
  • 1
  • 2
  • 10
  • 1
    Don't worry about RAM. Understand what the difference is between those two declarations. – Sotirios Delimanolis Oct 22 '13 at 22:16
  • hex, I am referring to something that the listed question does not: What about if the String gets mutated in some way? Strings are immutable, but the core String could possibly be overwritten in some way... – Aviator45003 Oct 22 '13 at 22:20
  • 2
    @T.C.: There could also be a cosmic ray pass through your memory and change a bit, better get ECC Memory. /s. But seriously, you don't have to worry about a String becoming changed in memory – Craig Oct 22 '13 at 22:22
  • Strings are immutable. – bmargulies Oct 22 '13 at 22:29
  • 1
    It's worth noting that string interning is up to the individual compiler (or the JVM?), so `a == b` is not a guaranteed behavior. I seem to remember that the typical implementation currently is to auto-intern strings that have less than 128 characters. After that, `a != b`. It's best just to get used to using .equals() always, and avoid the trouble in the first place. – StriplingWarrior Oct 22 '13 at 22:34

3 Answers3

3

When you use strings literal string can be interned ie this:-

 String b = "Hi"; 

but when you use new String("Hi") you get a new string object.

So

String s1 = new String("hi");
String s2 = new String("hi");
System.out.println(s1 == s2);  // False

Is the declaration for b really safe

As I said when you use strings literal string can be interned

Interning strings makes some string processing tasks more time- or space-efficient at the cost of requiring more time when the string is created or interned. The distinct values are stored in a string intern pool.

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
2

However, my Java text and C knowledge gravely inform me that since a==b as well as a.equals(b), if a is changed (Not likely in a String, but what if it gets mutated anyhow, as it is probably possible to pass the address somehow that even the JVM won't stop) then b will also be changed. As such, it could be dangerous to assume that b.equals("Hi").

It is absolutely the case that this is safe because Strings cannot be mutated. It's not possible to "pass the address somehow that even the JVM won't stop" without using JNI or some of the specifically labeled "Unsafe" APIs, in which case you can corrupt everything and all bets are off anyway, which is why those APIs are used only rarely and with extreme care. (In short, this is not a concern for 99.99% of Java programs.)

If a == b and a and b are references to mutable objects, then mutating the object referred to by a will absolutely affect b as well. But Strings aren't mutable, which is why things like interned literals are safe for Strings.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
0

The statements are not really equivalent. a references another object than b since you asked for it (aka you called new). a==b will evaluate to false.

However a equals b, and the objects referenced by a and b cannot be changed.

You cannot ever mutate a String in Java. Trying so (using JNI or whatever) will get you into serious trouble.

Axel
  • 13,939
  • 5
  • 50
  • 79