String is a rare class in Java. It's allowed to straddle the line between behaving as an object (using new() ) and behaving as a primitive )using direct assignment. The designers knew String objects would be prominent in almost any program. To conserve the run-time cost of creating them, they chose to allow static String assignments. Static assignments are "paid for" at compilation time, where they can be less of a burden.
When you allocate space for a String using new, that object goes to the heap and is garbage-collectible once it's fully dereferenced. A static String remains in program memory no matter what. Even if you completely dereference it, it's there and will get used again if you re-assign its value.
-- Michael Ernest, co-author of: The Complete Java 2 Certification Study Guide
A new String is already null. Trying to create a second null String is confusing the compiler. StringBuffer, on the other hand, is "just" another object.
If you want to assign null to a String reference, try
String s = null;
[ February 05, 2005: Message edited by: Marilyn de Queiroz ]
In contrast, StringBuffer has only one constructor that accepts an argument that could be null: one that takes a String.
If you write, for example,
String s = new String((char) null);
this will compile, as you're telling the compiler what you mean. Of course, then you'll get an error at runtime!
[MdQ]: A new String is already null.
I can't imagine what is meant by this statement. Perhaps you're saying the reference would be null? Not the object itself, surely? Of course the reference is only null if you don't initialize it to something else...
Michael Ernest's quote seems to be about string literals, though he calls them static strings for some reason. I can't see how it has anything to do with the question at hand. The reason that the compiler considers new String(null) to be ambiguous is because String has multiple constructors which take a single reference type as an argument:
public String(byte arr)
public String(char arr)
public String(String s)
public String(StringBuffer sb)
public String(StringBuilder sb) (JDK 1.5)
When you say new String(null), the compiler has no way of knowing which of these is intended, since null could be any of those four or five types. You could fix this by telling the compiler which one to use, with a cast. E.g.:
new String((char) null)
In contrast, StringBuffer has only two constructors which take a single reference type:
public StringBuffer(String s)
public StringBuffer(CharSequence cs)
Why does the compiler not consider new StringBuffer(null) to be ambiguous, given that there is more than one constructor that seems applicable here? The reason for this is somewhat subtle - it's because String is a subtype of CharSequence, and the JLS requires that the compiler choose the most specific interpretation of the type of null, from all possible interpretations. String is a more specific subtype of CharSequence, so the compiler assumes that null is of type String, and proceeds accordingly. Looking back at the String constructor - none of the argument types is more specific than all the others. In fact none are more specific than any of the others - none is a subtype of one of the other argument types. String is not a subtype of byte; byte is not a subtype of char, etc.
Now, why anyone would want to do anything like this - passing a null to a String or StringBuffer constructor - is another question. Passing null into one of these constructors would cause a NullPointerException at runtime. There's no possible benefit to doing something like this. So...
[MdQ]: If you want to assign null to a String reference, try
String s = null;
This, I agree with.