1. Introduction

Java String is one of the most important classes and we’ve already covered a lot of its aspects in our String-related series of tutorials.

In this tutorial, we’ll focus on String initialization in Java.

2. Creation

First of all, we should remember how Strings are created in Java.

We can use the new keyword or the literal syntax:

String usingNew = new String("baeldung");
String usingLiteral = "baeldung";

And, it’s also important that we understand how Strings are managed in a specialized pool.

3. String Declaration Only

First, let’s just declare a String, without assigning a value explicitly.

We can either do this locally or as a member variable:

public class StringInitialization {

    String fieldString;

    void printDeclaredOnlyString() {
        String localVarString;
        // System.out.println(localVarString); -> compilation error

As we can see, if we try to use localVarString before giving it a value, we’ll get a compilation error. On the other hand, the console will show “null” for fieldString‘s value.

See, member variables are initialized with a default value when the class is constructed, null in String‘s case. But, we have to initialize local variables ourselves.

If we give localVarString a value of null, we’ll see that the two are, indeed, now equal:

String localVarString = null;
assertEquals(fieldString, localVarString);

4. String Initialization Using Literals

Let’s now create two Strings using the same literal:

String literalOne = "Baeldung";
String literalTwo = "Baeldung";

We’ll confirm that only one object is created by comparing the references:

assertTrue(literalOne == literalTwo);

The reason for this harks back to the fact that Strings are stored in a poolliteralOne adds the String “baeldung” to the pool, and literalTwo reuses it.

5. String Initialization Using new

We’ll see some different behavior, though, if we use the new keyword.

String newStringOne = new String("Baeldung");
String newStringTwo = new String("Baeldung");

Although the value of both Strings will be the same as earlier, we’ll have to different objects this time:

assertFalse(newStringOne == newStringTwo);

6. Empty Strings

Let’s now create three empty Strings:

String emptyLiteral = "";
String emptyNewString = new String("");
String emptyNewStringTwo = new String();

As we know by now, the emptyLiteral will be added to the String pool, while the other two go directly onto the heap.

Although these won’t be the same objects, all of them will have the same value:

assertFalse(emptyLiteral == emptyNewString)
assertFalse(emptyLiteral == emptyNewStringTwo)
assertFalse(emptyNewString == emptyNewStringTwo)
assertEquals(emptyLiteral, emptyNewString);
assertEquals(emptyNewString, emptyNewStringTwo);

7. null Values

Finally, let’s see how null Strings behave.

Let’s declare and initialize a null String:

String nullValue = null;

If we printed nullValue, we’d see the word “null”, as we previously saw. And, if we tried to invoke any methods on nullValue, we’d get a NullPointerException, as expected.

But, why does “null” is being printed? What is null actually?

Well, the JVM specification says that null is the default value for all references, so it’s not specifically tied to the String. And actually, the specification doesn’t mandate any concrete value encoding for null.

So, where is “null” coming from for printing a String then?

If we take a look at the *PrintStream#*println implementation, we’ll see it calls String#valueOf:

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {

And, if we look at String#valueOf, we get our answer:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();

And, obviously, that’s the reason for “null”.

8. Conclusion

In this article, we explored String initialization. We explained the difference between declaration and initialization. We also touched on using new and using the literal syntax.

Finally, we took a look at what it means to assign a null value to a String, how the null value is represented in memory, and how it looks when we print it.

All code samples used in the article are available over on Github.

« 上一篇: Java Weekly, 第281期