6

I often saw people saying String str = new String("my string") is less efficient than writing String str = "my string", because the former creates a static "my string" object and then new's a String object that gets copied from the static one.

However, given that the language here is so simple and unambiguous, I can hardly imagine that Java optimizer won't take any effort to simply convert the former to the latter. Why would it really choose to do it the more laborious way? What can any negative side effects be if Java does optimize it?

Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
OneZero
  • 11,556
  • 15
  • 55
  • 92
  • 2
    did you learn this http://stackoverflow.com/questions/3052442/what-is-the-difference-between-text-and-new-stringtext – Youcef LAIDANI Mar 30 '17 at 20:11
  • 3
    It's not actually accurate to describe interned strings as "static", because they don't belong to any given class. Anyway, objects aren't "static" or "instance-level", only references to them are. – Lew Bloch Mar 30 '17 at 20:14
  • 2
    It is indeed simple and unambiguous: by the language specification, invoking a constructor [must create a new object](http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.9.4-200). Your proposed optimization would violate that rule. – shmosel Mar 30 '17 at 20:17

4 Answers4

9

However, given that the language here is so simple and unambiguous, I can hardly imagine that Java optimizer won't take any effort to simply convert the former to the latter.

First, you shouldn't write code saying to do something slow just because you think the compiler will replace it with something faster.

Second, the compiler can't generally optimize this, because new guarantees the creation of a new object. If you do

String str = new String("my string");

then it's guaranteed that str != "my string". Java can only optimize out the new if it can prove that the String object's identity won't matter to the execution of the program.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • 2
    [*Every time the \[class instance creation\] expression is evaluated, a fresh object is created.*](http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.9.4-200) – shmosel Mar 30 '17 at 20:12
6

Have a look into the generated bytecode for String s1 = "1":

LDC "1"
ASTORE 1

And for String s2 = new String("2"):

NEW java/lang/String
DUP
LDC "2"
INVOKESPECIAL java/lang/String.<init> (Ljava/lang/String;)V
ASTORE 2

The latter example is redundant and more complicated. Compiler won't make any optimizations in this case. It is guaranteed that a new instance of a String class will be created.

With a String str = "my string" the JVM can reuse instance of a String instead of creating a new one. Consider next examples:

String s1 = "1";
String s2 = "1";
System.out.println(s1 == s2); // true  => same reference, s1 & s2 point to the same object

String s3 = "1";
String s4 = new String("1");
System.out.println(s3 == s4); // false => s3 & s4 point to different objects
Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
2

You should always write the simplest, clearest code you can. Developer efficiency is more important than processor efficiency 90+% of the time. So even if the JIT could optimise it, which it doesn't, you are placing a burden on the developer to work out; why is this code more complicated than it needs to be? and the hardest answer to find is; no good reason at all.

Why would it really choose to do it the more laborious way?

When people migrate from other languages like C++ they take their idioms with them. In C++ for example you would need to write new string("some text") but in Java this is needlessly redundant.

What can any negative side effects be if Java does optimize it?

Java can optimise it with escape analysis. If the String doesn't escape the current method after inlining, the new String can be places on the stack and thus eliminated as it's redundant. But that is beside the point. You have already made life harder for anyone who has to maintain the code and the JIT won't help you with that.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

It's not an issue of performance. It's just doing something in an unnecessarily complicated way. Unless you're working with interned Strings to do comparisons with ==, the code will work the same way too.

Java won't optimize anything because there's nothing to optimize. If you use String literals, identical ones are reduced to the same instance in the string pool, so

String foo = "foo";
String bar = "foo";
System.out.println(foo == bar); // True, the same object

However with the explicit constructor

String foo = "foo";
String bar = new String("foo");
System.out.println(foo == bar); // False, bar is explicitly created as a new object with the constructor

However as you still should use equals() for all object comparisons, you won't see any difference while running your code.

Kayaman
  • 72,141
  • 5
  • 83
  • 121