-2

I wanted to know if it is the same to do this, in terms of optimization and performance:

public class Test {

    public static void main(String[] args) {        

        String option1 = "Text 1";
        String option2 = "Text 2";
        String option3 = "Text 3";

}

Than the following:

public class Test {

    public static void main(String[] args) {        

        String option1 = new String("Text 1");
        String option2 = new String("Text 2");
        String option3 = new String("Text 3");

}
Max Spring
  • 7
  • 1
  • 1
  • 4

3 Answers3

1

The second option will make a copy of the original string. This is probably not what you want, as if you do it on a memory-constrained platform or if you perform the operation a large number of times, you will cause a lot of garbage collection and, ultimately, an OutOfMemoryError.

As an example, I have created the following example.

public class Outie {

    public static void main(String[] args) {
        java.util.ArrayList<String> al = new java.util.ArrayList<String>();
        while (true) {
            al.add(new String("Outie"));
        }
    }
}

When compiled and run, incremental and full gc are run several times before the program abends.

$ java -verbosegc Outie
[GC 27648K->21021K(106048K), 0.0232500 secs]
[GC 48669K->39738K(133696K), 0.0251830 secs]
[GC 82898K->82549K(138880K), 0.0513920 secs]
[Full GC 82549K->75130K(226880K), 0.6177140 secs]
[GC 124479K->139363K(252672K), 0.0547170 secs]
[Full GC 139363K->112517K(352448K), 0.6634360 secs]
[GC 185168K->208879K(381952K), 0.0711140 secs]
[Full GC 208879K->168535K(515520K), 1.1115060 secs]
[GC 277163K->312989K(571200K), 0.1107330 secs]
[GC 379933K->307985K(615616K), 0.1115700 secs]
[GC 374929K->374905K(618944K), 0.1452780 secs]
[GC 521181K->467291K(650752K), 0.7257080 secs]
[GC 532443K->532619K(687936K), 1.1450690 secs]
[Full GC 532619K->507837K(965824K), 3.0001520 secs]
[GC 720339K->720812K(965824K), 0.8367880 secs]
[GC 811628K->811932K(998976K), 0.8454970 secs]
[Full GC 811932K->730029K(1352448K), 3.9708660 secs]
[GC 1036526K->1037014K(1352448K), 0.8832300 secs]
[GC 1160982K->1161502K(1400576K), 0.8352880 secs]
[Full GC 1161502K->1038805K(1544192K), 5.5201590 secs]
[GC 1205141K->1205495K(1544192K), 0.9881680 secs]
[GC-- 1281377K->1423593K(1544192K), 1.6090210 secs]
[Full GC 1423593K->1277979K(1544192K), 7.9840780 secs]
[Full GC 1277979K->1277965K(1544192K), 6.1397000 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:213)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:187)
    at java.util.ArrayList.add(ArrayList.java:411)
    at Outie.main(Outie.java:6)
Art Taylor
  • 1,188
  • 10
  • 19
  • 2
    "you will cause a lot of garbage collection and, ultimately, an `OutOfMemoryError`." - this sounds bogus. Either compile-time literals can be garbage collected in which case they will be and the memory use will be the same as if you assigned the literals directly. Or they can't in which case they won't, and you'll have a small amount of overhead per field. (Assuming said platform reuses `char` arrays as the regular JDK does.) Obviously the copies are *unnecessary* but there's no need to imagine outlandish bad consequences. – millimoose May 13 '13 at 23:35
  • @ArtTaylor Don't you think the **infinite loop** is kind of the bigger problem there? Without the copying you'll still run out of memory eventually as the array underlying the `ArrayList` has to be bigger than the heap. – millimoose May 13 '13 at 23:48
  • @millimoose No, the infinite loop is intended to demonstrate the problem as quickly as possible. – Art Taylor May 13 '13 at 23:50
  • @ArtTaylor That's completely insane. – millimoose May 13 '13 at 23:50
  • @ArtTaylor Yes. Memory leaks occur when your memory use grows *beyond any bound.* Like when you allocate memory in an infinite loop. *That* is the root cause of your code snippet running out of memory, not the constant per-string overhead of a few bytes. – millimoose May 13 '13 at 23:51
  • @ArtTaylor It doesn't matter how long a program runs. A memory leak occurs when you *keep allocating more and more memory* as the program keeps running. It doesn't matter whether it's on `String` objects or on resizing an `ArrayList` or wherever. The code in your example will eventually run out of memory even if you just do `al.add("");` or even `al.add(null);`. Thus, it's the infinite loop that's the problem, it doesn't just make it manifest quicker. – millimoose May 13 '13 at 23:55
  • @ArtTaylor What I'm trying to say is that eliminating the waste will not prevent a memory leak, thus said waste isn't the cause of the leak in the first place. Even if you keep too many references to the interned string, the program will leak / run out of memory. Also, I know what interned strings are, and comparing strings using `==` is terrible practice. (`equals()` does that as an optimisation, and won't break if one of the strings isn't interned.) – millimoose May 14 '13 at 00:00
  • 1
    @ArtTaylor No, I'm disagreeing about what the *root cause* of a memory leak is, and what's just an *aggravating factor*. You claim it's the overhead - for example, from the string copies - that *causes* a memory leak, while the infinite loop makes it manifest *quicker*. I maintain that it's the **exact opposite**: it is an infinite loop / some other structural error that is the *cause* of the leak; memory constraints, high operation volume, and incremental overhead are what makes the underlying memory leak appear *quicker*. Getting rid of the overhead will merely *delay* an `OOM`. – millimoose May 14 '13 at 00:22
-1

string literals are actually objects themselves, so first one should be better. But it makes no difference IMO

bilal.haider
  • 318
  • 1
  • 4
  • 18
  • Well string literals have a reference in string literals pool, which can have great effect on performance specially when duplicate string literals are used [JavaRanch](http://www.javaranch.com/journal/200409/Journal200409.jsp). – Rao Ehsan Jul 19 '13 at 06:13
-2

You can answer your question by using simple logic. Like so:

Suppose, new String("foo") would be, in some sense, "better" than just "foo". It immediately follows that new String(new String("foo")) would be even better. And so forth.

Clearly, this is nonsense. Nobody writes

new String(new String(new String("foo"))) 

Hence, you can just use "foo".

Ingo
  • 36,037
  • 5
  • 53
  • 100
  • -1: This is pretty much anti-logic. If Java's `String`s were mutable (which they're not), then making a single copy would make a lot of sense in that it would avoid clobbering the copied value. Even if making a double copy would not. – millimoose May 13 '13 at 23:39
  • The fact that *nobody writes* doesn't mean how it should be. For example, I can find lot of people using scriptlets and even teaching them to build real world apps. – Luiggi Mendoza May 13 '13 at 23:39
  • @millimoose I think in the explicit context of Java we need not consider what would be the case if Strings were mutable. – Ingo May 13 '13 at 23:41
  • 1
    @Ingo That doesn't mean your "logical" reasoning isn't completely nonsensical. For **any mutable object**, making a copy is "better" - avoids unintentionally clobbering the value. Making a double copy is not. – millimoose May 13 '13 at 23:41
  • @millimoose To the contrary. It makes sense in the given context and assuming the things as they really are (i.e. immutable). – Ingo May 13 '13 at 23:43
  • 1
    @Ingo Okay but then your "explanation" relies on the property of immutability which you don't even mention, and the OP certainly isn't assuming otherwise they'd probably figure this out themselves. Thus, your answer doesn't actually have any content. The logic fails for mutable objects, and immutability isn't mentioned as a premise. And "it immediately follows that a double copy would be even better" in and of itself is just a ridiculous statement - it's not a conclusion that follows "a copy is better than no copy". – millimoose May 13 '13 at 23:43