This is because you are invoking a method on a null object, therefore you get a NullPointerException !
However when you do "".equals(teststring) you are actually invoking the equals methods of the "" String (if it's easier to you, consider "" as new String("")). Also note that it is considered as a best practice to call the .equals() method on the "safe" string (the one we know that is not null !).
For the third assertion, "null" is display simply because under the hood println calls a method print which is the following :
/**
* Prints a string. If the argument is <code>null</code> then the string
* <code>"null"</code> is printed. Otherwise, the string's characters are
* converted into bytes according to the platform's default character
* encoding, and these bytes are written in exactly the manner of the
* <code>{@link #write(int)}</code> method.
*
* @param s The <code>String</code> to be printed
*/
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
So we can clearly see that there is a special case for null Strings !
I would strongly suggest you to read up : https://docs.oracle.com/javase/7/docs/api/java/lang/NullPointerException.html which is the official documentation of the NPE