3

Having never worked with Java much before, I was teaching myself generics syntax. I was testing out the simple generic function with some strings, and noticed something a little strange:

public class Main {

    public static <T> boolean areSameReference(T lhs, T rhs) {
        return lhs == rhs;
    }

    public static void main(String[] args) {
        String s = new String("test1");
        String t = s;
        String u = new String("test1");

        System.out.println(areSameReference(s, t)); //true
        System.out.println(areSameReference(s, u)); //false

        String v = "test2";
        String w = "test2";
        System.out.println(areSameReference(v, w)); //true
    }
}

How come [s] and [u] are different references, but [v] and [w] are the same reference? I would have thought that with or without "new" the string literal would have caused them to be the same or different consistently in both cases.

Am I missing something else going on here?

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • Look at [this question](http://stackoverflow.com/questions/2486191/java-string-pool). – Keppil Mar 12 '13 at 21:18
  • I'll just leave this here: http://stackoverflow.com/questions/334518/java-strings-string-s-new-stringsilly :-) – cklab Mar 12 '13 at 21:21

5 Answers5

4

How come [s] and [u] are different references,

Because you told the compiler you wanted new strings, didn't you?

Ingo
  • 36,037
  • 5
  • 53
  • 100
  • 1
    +1. If the _user_ asks for a new `String`; the user will get a new `String`. Don't blame the compiler for giving the programmer what they specifically asked for. – Louis Wasserman Mar 12 '13 at 21:33
3

As per JLS 3.10.5

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.

     String v = "test2";
     String w = "test2";

Will be considered as String literals.

When you use new operator to construct a String object it allocates new String object.

kosa
  • 65,990
  • 13
  • 130
  • 167
  • Out of curiosity, why isn't {String s = new String("test1");} a constant expression? I see that new is used, but I'd have thought the compiler or the String class would have been smart enough to realize it's the same string, strings are immutable, and use the same reference. – John Humphreys Mar 12 '13 at 21:22
  • 1
    @w00te Then somebody would come along and complain that he get the same old references despite he required new ones. – Ingo Mar 12 '13 at 21:23
  • @w00te: Alex, answer might have answer for your comment. When you call new String(....), as per javadoc, it creates new object. – kosa Mar 12 '13 at 21:23
  • To be fair, you are asking the JVM for a `new` String (it looks like it is listening to you as `new` overrides this behavior) – Jason Sperske Mar 12 '13 at 21:24
  • Thank you all for the help :) – John Humphreys Mar 12 '13 at 21:37
1

With new, you invoke the memory management system and get a new object.

Without new, the compiler optimizes the string contents into one entry in the '.class' constant table, resulting in two accesses to the same entry in the '.class' constant table.

The = comparison operator in Java is a reference comparison operation, so you will see differences between the two techniques. You might be able to hide those differences with enough use of String.intern(otherString).

The lesson to take home here is that except in extreme circumstances, always use .equals(...) to compare to objects.

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
1

The JVM keeps a pool of strings so that it doesn't waste memory with duplicate strings. Therefore, v and w should be the same. I'm guessing that the behavior that you're experiencing is due to the contract implied in the new String(String original) constructor, which indicates that it creates a new object (see http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#String(java.lang.String)).

Alex
  • 349
  • 1
  • 10
1

String objects are immutable, where string references are mutable. When you define "s" and "u", new objects for each are created. Value here does not matter because you invoke constructor, but when you assign same value to different String objects, they become references to same "test2" object in memory.

I would recommend reading more about immutable objects in Java, a good article is here: http://javarevisited.blogspot.com/2010/10/why-string-is-immutable-in-java.html

Petros P
  • 99
  • 8