2

Let's say I have a class as follows:

class Apple {

    String apple;

    Apple(String apple) {
        this.apple = apple;
    }
}

What makes the following code true?

public boolean result() {
    Apple a = new Apple("apple");
    Apple b = new Apple("apple");

    return a.apple == b.apple;
}

Does Java automatically intern Strings set within instances of my objects?

Is the only time that Java doesn't intern Strings is when they're created using new String("...")?

EDIT:

Thanks for the answers, an extension to this question would then be to say

Apple a = new Apple(new String("apple"));
Apple b = new Apple(new String("apple"));

returns false with the same test.

This is because I am passing an instance of String into the constructor as opposed to a String literal.

jason0x43
  • 3,363
  • 1
  • 16
  • 15
wild_nothing
  • 2,845
  • 1
  • 35
  • 47

2 Answers2

4

Does Java automatically intern Strings set within instances of my objects?

The point is: when you create first Apple a, JVM provide an instance of String containing "apple". This String is added to StringPool.

So when you create the second Apple b, the String is reused, then you have same object reference in a.apple and b.apple:

EXAMPLE:

Apple a = new Apple("apple");
Apple b = new Apple(new String("apple"));

System.out.println(a.apple == b.apple);

OUTPUT:

false

Is the only time that Java doesn't intern Strings is when they're created using new String("...")?

If you compare String objects with == you compare object references, not content.

To compare the contents of a String use String::equals() or String::intern()

EXAMPLE

    // declaration
    String a = "a";
    String b = "a";
    String c = new String("a");

    // check references 
    System.out.println("AB>>" + (a == b));  // true, a & b references same memory position
    System.out.println("AC>>" + (a == c));  // false, a & c are different strings
    // as logic states if a == b && a != c then b != c.

    // using equals
    System.out.println("ACe>" + (a.equals(c))); // true, because compares content!!!!
     
    // using intern()
    System.out.println("ABi>" + (a.intern() == b.intern()));  // true
    System.out.println("BCi>" + (b.intern() == c.intern()));  // true

RELATED QUESTIONS

Community
  • 1
  • 1
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • Ah, I see. And even if I used Apple a = new Apple(new String("apple")); Apple b = new Apple(new String("apple")); the result would still be false. – wild_nothing Jul 12 '16 at 10:09
  • @wild_nothing yes, p`lease check my update, I hope it clarifies, but don't hesitate to ask if you need further clarification – Jordi Castilla Jul 12 '16 at 10:16
  • Can you answer this question above: Is the only time that Java doesn't intern Strings is when they're created using new String("...")? – markthegrea Oct 16 '18 at 13:36
  • @markthegrea actually it is already explained in the second part of the answer, you need clarification in some point?? – Jordi Castilla Oct 17 '18 at 16:47
  • Sorry, but I don't see it. Seems it is a yes or no question. You just have some examples that don't show if it is interned or not. – markthegrea Oct 18 '18 at 18:20
  • Sorry! I misread the answer and asked the incorrect question! Your answer indeed shows the intern logic, but what I want to know is: "Is the only time that Java doesn't intern Strings is when they're created using new String("...")?" We are trying to reduce garbage collection in our app and are interning lots of Strings. It seems most Strings are already interned. When are they NOT interned? – markthegrea Oct 29 '18 at 14:10
1

The field apple within Apple is a reference to a String.

In your case that reference is referring to an interned string, since you've instantiated the Apple using a string literal which will be interned.

And since a and b are created from the same interned string, a.apple refers to the same string as b.apple.

Indeed Java cannot intern a string if you use new String.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483