Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Java The Thing About Strings

Grigorij Schleifer
Grigorij Schleifer
10,365 Points

String pool question

Hey Java-fans,

I have trouble to understand the concepts of the String pool and the whole String equality topic. I understand how to compare primitive types using == sign and how to compare objects/reference variables using equals() method. BUT....

Why do we need a String literal after creating a String object. And the explanation that the Strings are immutable makes for me no sense?

And what is a single instance of an immutable String, so other variables can refer to that instance .... WHAAAAAT???? And why the String pool is keeping all this references ?

Sorry guys, I am burning from inside .... just want to get it right :)

Every help is appreciated

Grigorij

2 Answers

Gavin Ralston
Gavin Ralston
28,770 Points

Strings are immutable, meaning they can never be modified. Once they're created, they'll always exist like that for eternity (or until they're no longer needed, then they just go away)

So what he's saying is that the java compiler will identify duplicate strings, and instead of creating a new instance of them and having them all clutter up memory, all variables that point to it will point to exactly the same one.

String courseTeacher = "Craig";
String lumberJack = "Craig";
String suuuuupGuy = "Craig";
String dunkTankSitter = "Craig";

Rather than creating and storing four separate instances of the string "Craig" it'll just have one single instance where all of those variables point to. It's more economical.

With the second example, pretend that you collected user input while the program was running and stored it in the input variable

// You test equality before you collect user input, where both variables point to the same object, thanks to javac
System.out.println(courseTeacher == suuuuupGuy);
// Answer is true

// You collected input from the user, which, confusingly, was "Craig"
courseTeacher = input;
// then you go on to check equality again...

System.out.println(courseTeacher == suuuuupGuy);
// Answer is false

Because at some point while your program was running you had to create a new string object in order to get the input from the user and store it in the input variable, there's an entirely new object with the same string.

The compiler was already run and your program is actually running when you're collecting input, so a new object has to be created to store it, versus earlier on when javac could kind of look at everything and go "Oh, there's a bunch of variables pointing to the exact same string, I'll just make one and point them all there"

So courseTeacher still points to a String, and the string you got while the program was running was identical in content but it is an entirely separate object in memory.

That's why after the program started running, courseTeacher == lumberJack would not be equal, because they'd be pointing at two different instances of Strings that held the letters "Craig"

If you want to see if they have the same value you need to check the value of the object that the variable references.

However, when you use == the value you're actually checking is the address in memory of the object, whether that's a string or a Boat or a GoatHerder or whatever class you create.

So while you might mean to check the value of the string when you use == what you're really doing is comparing whether those variables hold the same address

Well, at least until you call intern() on the user input. :)

Here's some code you can read through, or download and compile, that might make more sense of it:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) {
        BufferedReader mReader = new BufferedReader(new InputStreamReader(System.in));
        String guyOne = "Craig";
        String guyTwo = "Craig";
        // javac will find "Craig" in the String Pool and point both variables to the same String object to save memory space

        System.out.printf("Compiled guyOne == guyTwo? %s%n", guyOne == guyTwo);

        System.out.print("Type the name 'Craig' here ---===>>>  ");

        try {
            // keep in mind your BufferedReader is going to return a new String object at runtime!
            guyOne = mReader.readLine().trim();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }

        /*
        Compare two different String objects here.  The one you have in String Pool, and the new one you
        assigned to guyOne at the prompt.
        */
        System.out.printf("The new guyOne == guyTwo? %s%n", guyOne == guyTwo);

        /*
        now internalize it. Which just puts it in the String Pool, and since "Craig" already exists there
        it makes guyOne reference the same "Craig" rather than having two strings in memory floating
        around with the same exact information...
        */
        System.out.printf("Internalized guyOne named 'Craig' == guyTwo? %s%n", guyOne.intern() == guyTwo);
    }
}

Output is as follows:

Compiled guyOne == guyTwo? true
Type the name 'Craig' here ---===>>>  Craig
The new guyOne == guyTwo? false
Internalized guyOne named 'Craig' == guyTwo? true

Process finished with exit code 0

The tl;dr: Use equals() when comparing objects for equality. == is only usually useful for comparing primitives

Grigorij Schleifer
Grigorij Schleifer
10,365 Points

Gavin,

damn great answer !!!!!

Thank you so much :)

Grigorij

Gavin Ralston
Gavin Ralston
28,770 Points

Thanks! Glad I could help.

I'm going to edit the answer and include some code people could download and run themselves, or just read here to see if it helps walk through what's happening.

Grigorij Schleifer
Grigorij Schleifer
10,365 Points

Hey Gavin,

yoa are awesome !!!

Thank you so much ...

Edward Strudwick
Edward Strudwick
2,036 Points

Ok, but why can you not just use a string literal for the input? Why does it have to come from a newly created object? So for mreader above I can see it uses the constructer method, but why does it have to? Why can it not simply use the String guyOne = method?

Damian Adams
Damian Adams
21,351 Points

For the sake of posterity and for newer readers that are joining us with a burning curiosity of Java Strings, here is an excellent resource that discusses more or less what you need to know about Strings in Java: https://www.ntu.edu.sg/home/ehchua/programming/java/J3d_String.html

Great work Gavin. I also had the same doubt, but you cleared it.

Thank you both.

The link Damian adam is shared is very useful one. thanks for that.