I was using IntelliJ and it said that a string needed to be initialized in order for the program to work. It suggests I initialize it this way
String example = null;
instead of
String example = "";
Do you agree with this? I've found conflicting information as to whether or not this is a good idea.
Assign null
When we write:
String s = "Hello World!";
s = null;
The String object still exists in memory because this does not delete it. However the garbage collector will clear the object from memory as there is no variable referencing it.
For all practical purposes s = null; deletes the String.
tl;dr
set a String to null in Java?
myString = null ;
declare the variable without initializing it
Uninitialized deaults to null, no String object. Empty reference variable.
String myString ;
You can explicitly assign null. Same effect as line above. No object, empty reference.
String name = null;
Declare and initialize to empty string:
String myString = "" ; // A `String` object containing no characters. Not null.
Details
Before posting here on basic Java Questions, study the Java Tutorials provided by Oracle free of cost.
See the tutorial page on string literals. To quote:
There's also a special
nullliteral that can be used as a value for any reference type.nullmay be assigned to any variable, except variables of primitive types. There's little you can do with anullvalue beyond testing for its presence. Therefore,nullis often used in programs as a marker to indicate that some object is unavailable.
So null is not a piece of text with four characters. The keyword null means “no object at all”, no String, nothing at all, an empty reference.
To test if an object reference variable is null (contains no reference), you have a few choices:
Objects.isNull( myVar )andObjects.nonNull( myVar )null == myVarandnull != myVarmyVar == nullandmyVar != null
I prefer the first, as words are easier to read than mathematical-like symbols.
You may also understand the difference between null and an empty string this way:

Original image by R. Sato (@raysato)
"" is an actual string, albeit an empty one.
null, however, means that the String variable points to nothing.
a==b returns false because "" and null do not occupy the same space in memory--in other words, their variables don't point to the same objects.
a.equals(b) returns false because "" does not equal null, obviously.
The difference is though that since "" is an actual string, you can still invoke methods or functions on it like
a.length()
a.substring(0, 1)
and so on.
If the String equals null, like b, Java would throw a NullPointerException if you tried invoking, say:
b.length()
If the difference you are wondering about is == versus equals, it's this:
== compares references, like if I went
String a = new String("");
String b = new String("");
System.out.println(a==b);
That would output false because I allocated two different objects, and a and b point to different objects.
However, a.equals(b) in this case would return true, because equals for Strings will return true if and only if the argument String is not null and represents the same sequence of characters.
Be warned, though, that Java does have a special case for Strings.
String a = "abc";
String b = "abc";
System.out.println(a==b);
You would think that the output would be false, since it should allocate two different Strings. Actually, Java will intern literal Strings (ones that are initialized like a and b in our example). So be careful, because that can give some false positives on how == works.
First let's clarify something: You mention that after assigning null to the variable you could forget to initialize it, but by assigning null to it you are in effect initializing it.
public static void main (String args[]){
String s;
System.out.println(s); // compiler error variable may not be initialized
}
vs
public static void main (String args[]){
String s=null;
System.out.println(s); // no compiler error
System.out.println(s.equals("helo")); // but this will generate an exception
}
So after you do String s=null; there's is no way that you could forget to initialize because you did initialize it.
That being clear, I would recommend you to use a "smart default". In your case perhaps the empty string "" would be a good default value if you want to avoid NullPointerException. In the other hand, sometimes it is desirable that the program produce an exception because it indicates something wrong happened under the hood that should not have happened.
In general you want to keep declaration and initialisation as close as possible to minimise exactly the type of problem you're talking about.
There is also the issue of redundant initialisation where the value null you're assigning is never used which is extra code that harms readability even if the redundant assignment is optimised away by the compiler.
Sometimes assigning some sort of default value is unavoidable, for example if you declare before a try catch, initialise inside and use it afterwards. For other types you can often find a more natural default value such as an empty list.
The string is initialised with no characters, or "" internally.
public String() {
this.offset = 0;
this.count = 0;
this.value = new char[0];
}
The above source is taken from the Java source code. As the other poster pointed out, references can either be null or point to an object, if you create a String object and get a reference to point to it, that reference will not be null.
"null" is a value for a variable, not a value for a String. "foo" can have null value, but an actual String cannot. What you have done is create a new empty String (as the documentation for the constructor says) and assigned it to foo.
That way lies madness (usually). If you're running into a lot of null pointer problems, that's because you're trying to use them before actually populating them. Those null pointer problems are loud obnoxious warning sirens telling you where that use is, allowing you to then go in and fix the problem. If you just initially set them to empty, then you'll be risking using them instead of what you were actually expecting there.
Absolutely not. An empty string and a null string are entirely different things and you should not confuse them.
To explain further:
- "null" means "I haven't initialized this variable, or it has no value"
- "empty string" means "I know what the value is, it's empty".
As Yuliy already mentioned, if you're seeing a lot of null pointer exceptions, it's because you are expecting things to have values when they don't, or you're being sloppy about initializing things before you use them. In either case, you should take the time to program properly - make sure things that should have values have those values, and make sure that if you're accessing the values of things that might not have value, that you take that into account.
Why must it work?
The JLS 5, Section 15.18.1.1 JLS 8 § 15.18.1 "String Concatenation Operator +", leading to JLS 8, § 5.1.11 "String Conversion", requires this operation to succeed without failure:
...Now only reference values need to be considered. If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.
How does it work?
Let's look at the bytecode! The compiler takes your code:
String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
and compiles it into bytecode as if you had instead written this:
String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"
(You can do so yourself by using javap -c)
The append methods of StringBuilder all handle null just fine. In this case because null is the first argument, String.valueOf() is invoked instead since StringBuilder does not have a constructor that takes any arbitrary reference type.
If you were to have done s = "hello" + s instead, the equivalent code would be:
s = new StringBuilder("hello").append(s).toString();
where in this case the append method takes the null and then delegates it to String.valueOf().
Note: String concatenation is actually one of the rare places where the compiler gets to decide which optimization(s) to perform. As such, the "exact equivalent" code may differ from compiler to compiler. This optimization is allowed by JLS, Section 15.18.1.2:
To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
The compiler I used to determine the "equivalent code" above was Eclipse's compiler, ecj.
See section 5.4 and 15.18 of the Java Language specification:
String conversion applies only to the operands of the binary + operator when one of the arguments is a String. In this single special case, the other argument to the + is converted to a String, and a new String which is the concatenation of the two strings is the result of the +. String conversion is specified in detail within the description of the string concatenation + operator.
and
If only one operand expression is of type String, then string conversion is performed on the other operand to produce a string at run time. The result is a reference to a String object (newly created, unless the expression is a compile-time constant expression (§15.28))that is the concatenation of the two operand strings. The characters of the left-hand operand precede the characters of the right-hand operand in the newly created string. If an operand of type String is null, then the string "null" is used instead of that operand.
Normally, when you call a constructor or method for which multiple overridden versions might apply, Java will choose the most specific constructor or method. Section 15.12.2 of the Java Language Specification explains this in detail.
Suppose you have two overloaded methods, like this:
public void method(Object o) {
// ...
}
public void method(String s) {
// ...
}
When you call method(null), both these methods apply. Java chooses the most specific one, which is in this case the second method, that takes a String - because String is a more specific type than Object.
However, sometimes the most specific constructor or method cannot be determined. If we look at the constructors of class String that take one argument:
String(byte[] bytes)
String(char[] value)
String(String original)
String(StringBuffer buffer)
String(StringBuilder builder)
Note that there is no hierarchy between the types byte[], char[], String, StringBuffer and StringBuilder, so it's not possible to say that one of these constructors is more specific than the others. So, the Java compiler doesn't know which constructor to choose and will give you an error.
Because, compiler couldn't figure out which constructor to call. See here that how many one-argument-constructor it has.
[Edited] You said, if there is another reason. So why not try out yourself. Do something like this,
byte[] b = null;
String s = new String(b); // complier should be fine with this
char[] c = null;
String s = new String(c); // complier should be fine with this
.... // you can try other constructors using similar approach.