ADJenks
ADJenks

Reputation: 3414

String objects which are not literal not requiring new keyword?

So I know there are other similar questions to this, such as this one and this other one. But Their answer seems to be that because they are literal and part of some pool of immutable literal constants, they will remain available. This sort of makes sense to me, but then why do non literals also work fine? When do I ever have to use the "new" keyword when dealing with strings. In the example below, I use strings to do a few things, but everything works fine and I never use the "new" keyword (correction: I never use it with a String type object).

import java.util.*;

class teststrings{

   public static void main(String[] args){
      Scanner in = new Scanner(System.in);
      String nonew;
      String nonew2;
      String literally= "old";
      literally= "new"; //does the word "old" get garbage collected here?
      nonew = in.nextLine(); //this does not use the new keyword, but it works, why?
      System.out.println("nonew:"+nonew);
      System.out.println("literally:"+literally);
      nonew2 = in.nextLine();
      System.out.println("nonew:"+nonew); //the data is still preserved here
      System.out.println("nonew2:"+nonew2);
      //I didn't use the new keyword at all, but everything worked
      //So, when do I need to use it?
   }

}

Upvotes: 1

Views: 146

Answers (2)

pczeus
pczeus

Reputation: 7867

Strings are treated specially in Java. The Java JVM makes use of a cache like implementation called a String pool.

Unlike other objects, when you create a literal String like this: String mystring = "Hello"; Java will first check to see if the String "Hello" already exists in the String pool. If not, it will add it to be cached and reused if referenced again.

So, when you assign a variable to "Hello" the first time, it gets added to the pool:

String s1 = "Hello";
String s2 = "Hello";
String s3 = s1;
s1 = "SomethingElse"

In the code above, when s1 is assigned "Hello" the JVM will see it is not stored in the pool and create/add it to the pool. For s2, you are again referencing "Hello". The JVM will see it in the pool and assign s2 to the same String stored in the pool. s3 is simply assigned to the value referenced at the memory address of s1, or the same string "Hello". Finally, s1 is then reassigned to another String, which doesn't exist yet in the pool, so is added. Also, s1 no longer points to "Hello", yet it will not be garbage collected, for two reasons. 1:t is being stored in the String pool and 2: s2 also points to the same referenced string.

With Strings, you should never use the new keyword for creating literal strings. If you do, you are not taking advantage of the String pool reuse and could cause multiple instances of the same String to exist in memory, which is a waste.

Upvotes: 2

BeUndead
BeUndead

Reputation: 3618

A couple of points: "Does the word "old" get garbage collected here?" Chances are your compiler realises it's never used and just skips it altogether.

Scanner::nextLine returns a String, and the value returned by the method is used for the assignment.

As for when to use new for Strings... Well, rarely would probably be best. The only time I've ever seen it used would be for internal constants. For example

public class MatchChecker {
    private static final String ANY_VALUE = new String("*");

    private final Map<Object, String> map = new HashMap<Object, String>();

    public void addMatch(Object object, String string) {
        map.put(object, string);
    }

    public void addAnyValueMatch(Object object) {
        map.put(object, ANY_VALUE);
    }

    public boolean matches(Object object, String string) {
        if (!map.contains(object)) {
            return false;
        }
        if (map.get(object) == ANY_VALUE || map.get(object).equals(string)) {
            return true;
        }
        return false;
    }
}

Which would mean only those Objects added via addAnyValueMatch would match any value (as it's tested with ==), even if the user used "*" as the string in addMatch.

Upvotes: 2

Related Questions