Why does Java cast the null reference to String "null"? [duplicate] - java

This question already has answers here:
Why does null reference print as "null"
(3 answers)
Closed 6 years ago.
In Java, if I write:
System.out.println((String) null);, I get "null".
This seems weird. Does anyone know why the designers chose this approach? It seems to me that this is a case of "creating something out of nothing". I've read the JLS entry on cast operators, and it says:
The type of a cast expression is the result of applying capture conversion (§5.1.10) to the type whose name appears within the parentheses.
The result of a cast expression is not a variable, but a value, even if the result of the operand expression is a variable.
Jumping to the entry on capture conversion, I see capture conversion defined for generic types, but the entry adds:
Capture conversion on any type other than a parameterized type (§4.5) acts as an identity conversion (§5.1.1).
Okay! On to the entry on identity conversion and there's this:
A conversion from a type to that same type is permitted for any type.
In this case, the type is String but the thing to be converted is null and that left me confused. However, it turns out that Java is actually using String conversion for (String) null. The JLS entry on String conversion says:
Any type may be converted to type String by string conversion...
If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
One problem that this raises is this:
HashMap map = new HashMap();
System.out.println((String)map.get("something"));
The program prints "null". How do I know whether it was that because entry was null versus the String in the HashMap has value "null" (four ASCII characters 'n', 'u', 'l', 'l')? Now I know someone will say that Java discourages the use of raw types, and that the type HashMap should be parameterized but is that the solution?

You are overthinking this. Java is not casting (the value) null to (the string) "null". The correct answer is that this is merely an explicit behavior of the PrintStream.println(String) method:
Prints a String and then terminate the line. This method behaves as though it invokes print(String) and then println().
Next we consult what PrintStream.print(String) has to say:
Prints a string. If the argument is null then the string "null" 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 write(int) method.
(Remember, the type of System.out is PrintStream.)

HashMap map = new HashMap();
System.out.println((String)map.get("something"));
The program prints "null". How do I know whether it was that because
entry was null versus the String in the HashMap has value "null"
(four ASCII characters 'n', 'u', 'l', 'l')?
There's still a difference between null and "null", you just can't see that when you print them out with System.out.println. They're different values, and they do compare differently:
HashMap map = new HashMap();
map.put("foo", "null");
String something = (String) map.get("something");
String foo = (String) map.get("foo");
System.out.println(something == null); // true
System.out.println(foo == null); // false
System.out.println("null".equals(something)); // false
System.out.println("null".equals(foo)); // true

It does nothing to do with casting, but with printing: If you cast a null to String, it is still a null:
String s=(String)null;
if (s==null)
{
System.out.println("It is still a null");
}
else
{
throw new RuntimeException("This won't happen");
}
So you shouldn't have any difficulties to check if a value returned by a Map, Collection, or whatever API is null or not, simply performing a direct comparation by program.
In the other hand, never trust the result printed directly to the standard output by a PrintStream (as System.out). See the documentation of PrintStream.print(String).
Moreover: The same ambiguity happens when printing a number or a boolean: If you see on the standard output "123", is it a number value or a string value? I insist: To check values, never trust the appearance of a string printed out to a PrintStream.

Related

String array vs String split array [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 7 years ago.
String s = "Hi Hello Hola";
String[] d = s.split(" ");
System.out.println(d[0] == "Hi"); // prints false
String[] e = { "Hi", "Hello", "Hola" };
System.out.println(e[0] == "Hi"); // prints true
Here we have an array d with the values Hi, Hello, and Hola. We have another array e with the same set of values.
But why does this comparison behaves differently? Why does it print false and then true?
I expected false for both! As we are comparing a string literal value with the string value by using ==.
Why is this difference?
Update Here my question is not about the comparison of String values. I'm aware of the differences between == which compares the references and equals() which compares the content of the string.
From the answers, i understand that in the second case, Hi value is interned and refers to the same object. But in the other case, split creates new values without checking the literal pool. Is it right? Am i missing anything?
The reason beeing is the compiler. At compile time the compiler does notice that the literal Hi exists twice in the code and does intern this string for your specific class.
After compilation both of your interned strings Hi are pointing to the same reference of Hi. That´s the reason why the second print results in true.
The split doesn´t know it´s result and creates new references for the corresponding Strings. That´s the reson why Hi from the split and the literal Hi are not using the same reference.
This is happening because internally when split(Pattern) matches the pattern, and finds the matching char sequences, then it uses String.substring(start,end) for creating a new String object. That is why results returned by split are false. This is code snippet from java.util.regex.Pattern.split(CharSequence input, int limit) class.
String match = input.subSequence(index, m.start()).toString();
Here the input is instance of the String class, which is passed to the Pattern.split(CharSequence, int) method.
Reference: Pattern
Trying to use '==' on strings is very unpredictable. The first time you type in "Hi" as a literal, it is saved into memory. When you then assign it into the array 'e', it uses that same saved literal for storing it in the array. When you then check to see if they are equal, it resolves as true.
I highly recommend not using '==' and use one of the many methods that are provided in Java.
System.out.println("Hi".equals(d[0]));
System.out.println("Hi".equals(e[0]));
or...
System.out.println(("Hi".compareTo(d[0]) == 0));
System.out.println(("Hi".compareTo(e[0]) == 0));

What does is mean by null pointing to nothing and why use null at all?

There are a lot of questions about null and in java.
What I am failing to grasp is what people mean by null is pointing to nothing or why to use null at all.
I can't understand the difference between
String thing = null;
and
String thing = "";
This question has detailed answers What is null in Java?, but I just can't wrap my head around it.
What am I missing?
languages I've studied (no expert)
Python, vb (vb.net), web programming (html, css, php, bit of js), sql
I should add, it is this answer https://stackoverflow.com/a/19697058/2776866 which prompted me to write this.
String str = null;
means a String reference, named str, not pointing to anything
String str = "";
means a String reference, named str, pointing to an actual String instance. And for that String instance, it is a zero-length String, but it is still an actual object.
Just a little update with some diagram which hopefully can help you visualize that:
assume I have
String nullStr = null;
String emptyStr = "";
String myStr = "ab";
What it conceptually is something look like:
// String nullStr = null;
nullStr ----------> X pointing to nothing
// String emptyStr = "";
+------------------+
emptyStr ---------> | String |
+------------------+
| length = 0 |
| content = [] |
+------------------+
// String myStr = "ab";
+------------------+
myStr ------------> | String |
+------------------+
| length = 2 |
| content = [ab] |
+------------------+
(of course the internal structure of the String object is not the real thing in Java, it is just for giving you an idea)
More edit for the rationale behind NULL:
In fact in some language they do not provide concept of NULL. Anyway, in Java (or similar language), Null means semantically different from "empty" object. Use String as an example, I may have a People class with a String preferedTitle attribute. A Null preferedTitle means there is NO preferred title for that people (so that we need to derive and show the title for it, maybe), while a preferedTitle being an empty string means there IS a preferred title, and that's showing nothing.
Btw, although a bit off topic: concept of Null is seen as problematic for some people (because all those extra handling it need etc). Hence some languages (e.g. Haskell) are using some other ways to handle the situation where we used to use Null.
String str is a reference to an object. That is, it's not an actual object, but a variable which can contain the address of an object. When you assign a value to str you are changing the address stored within and changing which object it addresses.
null is reference value which points to no object. It's about as close to nothing as you can get. If you assign null to a String reference (String str = null;), you cannot then invoke any method of String using that reference -- all attempts will result in NullPointerException.
"" is a character String which contains no characters -- zero length. It is still an object, though, and if you assign its address to your String reference variable (String str = "";) you can then take its length, compare it to another String, extract its hashCode, etc.
Java doesn't really expose pointers, instead it deals with references.
When you say
String thing = null;
You are saying that there is a reference (of type string) called thing, which isn't referencing anything.
When you say
String thing = ""
This is shorthand for,
String thing = new String("");
Now you have an actual object initialized and ready to be used. You told the compiler to create a string and now your "thing" references the new string.
If you want to know the length of your initialized string, you can go;
thing.length
Which is zero. The string exists, but is zero length.
Trying string.length on the null version causes a NullReferenceException, which is the compiler saying
"I tried to find out about the length of your string, but I couldn't find it!"
Practically speaking, null means "not available for calling methods". If an object is allowed to be null, you must always check it for null before calling method on it.
An attempt to call any method on a null object is unconditionally an error. In nearly all cases it's a programming error, too, because you are supposed to either
Ensure that a variable is always non-null, or
Check a variable that could legally be null before calling methods on it.
On the other hand, an empty object lets you call methods. For example, you can find the length of an empty string - it is zero. You could also iterate a string, pass it to methods that expect non-null strings, and so on.
To visualize this, consider a Boolean object instead of a String. Unlike the primitive boolean that has only two states, namely true ("yes") and false ("no"), the Boolean object has three states:
Yes
No
Don't know
This third "don't know" state corresponds to null. It's neither true nor false state. Your program can use this third state to its advantage - for example, you can use comparison to null to see if a value has been set, or set a value to null to "unset" its value.
In Java null and an empty String are two different things.
If an String is null then you can not access its methods as it will throw a NullPointerException, however if a String is "" then the String object is valid and you can access its methods.
For example
String a = null;
String b = "";
System.out.println (a.length()); // No Good
System.out.println (b.length()); // Prints 0
Let's compare this to Python. In Python, the equivalent to null is None.
>>> test = ""
>>> test1 = None
This is setting an empty string and a "null" string.
>>> test
''
>>> test1
None
In Python we can test nullity using is
>>> test is None
False
>>> test1 is None
True
We can test for empty strings using ==
>>> test == ""
True
>>> test1 == ""
False
null (like None) is the absence of a value.
Conceptually null is a special value which means that the variable points to an invalid object, so it doesn't refer to anything valid in the sense that you can't access its content (variables or methods).
You can see it as a sort of special condition which has been added to languages because it was useful to be able to have pointers that refer to nothing. But there is some discordance here, in fact some languages prevent the necessity of a null value by forcing you to have just inizialized (meaningful) values.
There is difference in your example, "" is a valid object: it's an empty string while null is not a valid object.
Although many object-oriented frameworks implement references with pointers, it is better to think of references not as "pointing to" objects, but rather as "identifying" them [personally, I like the term "object identifier" to describe references, since the term "reference" is somewhat overloaded in different contexts]. Although object identifiers are not human readable, one can imagine the system as giving each object an associated number starting at 1, and each class-type variable as either having an object number or a zero written on it. Since class-type variables and array slots default to holding zero, and there will never be a zeroth object, there's no danger that the default-valued variable of an uninitialized variable or array slot will identify a valid object.
I prefer using the concept of containers/boxes to understand this concept
Let's start with this
String thing = "";
Imagine you have a container/box where you can store any value as long as you put the value between double quote marks "", if you decide to just put the double quotation mark without a value inside the box there is absolutely nothing wrong with that and any time you open your box you still see something inside (The double quotation mark )
Now This big man over here called null
String thing = null;
In simple terms look at null as being absolutely nothing
What does all this mean?
When you open the first box you see the double quotation ""
When you open the second box you see nothing (it's just an empty box)

Assign property value with type conversion in Java

What is the best way to assign a value with type conversion to a property of an object in Java.
For eg: A Person class with age field as an integer. If the following statement has to assign integer 21 to age field, then what should be the implementation of set method? [Note: 21 is passed as string]
ObjectUtils.set(person, "age", "21");
One way is to get the type of the field and type cast explicitly. Is there any better approach or library utility available to achieve this?
Take a look at BeanUtils.setProperty():
Set the specified property value, performing type conversions as required to conform to the type of the destination property.
You can achieve this by using reflexion:
using this you can get the attribute type dynamically, something like this:
Person p = ...; // The object you want to inspect
Class<?> c = p.getClass();
Field f = c.getDeclaredField("age");
f.setAccessible(true);
String typeOfAge = (String) f.getType(p);
After you have the attribute type its easy to cast the value.
use Integer.parseInt(String) in your set method. Make sure you catch the exception for an invalid number. Here is hte javadoc for parseInt
parseInt
public static int parseInt(String s) throws NumberFormatException Parses the string
argument as a signed decimal integer. The characters in the string
must all be decimal digits, except that the first character may be an
ASCII minus sign '-' ('\u002D') to indicate a negative value. The
resulting integer value is returned, exactly as if the argument and
the radix 10 were given as arguments to the parseInt(java.lang.String,
int) method. Parameters: s - a String containing the int
representation to be parsed Returns: the integer value represented by
the argument in decimal. Throws: NumberFormatException - if the string
does not contain a parsable integer.

Java ternary operator function overloading [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java conditional operator ?: result type
NullPointerException through auto-boxing-behavior of Java ternary operator
Say I have two functions:
f(MyObject o) { ... }
f(int i) { ... }
And I call them like this:
f(someCondition ? 10 : null);
This compiles, but when I run it I get a null pointer exception (sorry I'm not sure on which condition). Some my questions are:
Why does it even compile? What is the type of foo ? 10 : null?
It clearly doesn't call the "correct" functions because that wouldn't cause an NPE. So which function is it calling? Does it do f((MyObject)10); or f((int)null)?
First of all, the problem doesn't have anything to do with the fact that you have overloaded versions of f. If you only have the version of f that takes an int, you get the same problem.
The thing is that both possible results of the ternary expression (before and after the :) must have the same type, because the whole expression condition ? expr1 : expr2 must have a single type. You can't have this expression evaluate to one type of condition is true, and another type if it is false.
So, the Java compiler is going to see if it can convert expr1 and expr2 to a single type. Note that int cannot be null (because it's a primitive type). However, 10 can be converted to Integer via autoboxing, and an Integer can also be null. So the type of the whole ternary expression is determined to be of type Integer. The result is either an Integer that contains the value 10 or an Integer that is null.
Step two is that you pass this Integer to f. Because f takes an int, it is auto-unboxed.
If you auto-unbox an Integer that is null, you get a NullPointerException - that's what happens here.
The type is Integer - an auto boxing is done to the 10.
f(int) is called, because it is the only accepted cast from Integer available (assuming no other overloads)
When you try to cast a null to an int - you get your NPE.
2. f(Object) is called since Integer is an Object. This is called reference type widening
(sorry for the initial mistake, read it as f(Object))

Understanding the difference between null and '\u000' in Java

I read in a book (Thinking in Java by Bruce Eckel, 4th edition, page 47) that null is equal to '\u000'. And then I was wondering what exactly does '\u000' really mean.
As per my understanding null was nothing or absence of anything. And '\u000' comes in contradiction with this definition.
Can anyone clarify this issue about null and '\u000'?
The language specification is where null is defined, and it says
There is also a special null type, the type of the expression null, which has no name. Because the null type has no name, it is impossible to declare a variable of the null type or to cast to the null type. The null reference is the only possible value of an expression of null type. The null reference can always be cast to any reference type. In practice, the programmer can ignore the null type and just pretend that null is merely a special literal that can be of any reference type. --Link to documentation (Section 4.1)
and
The null type has one value, the null reference, represented by the literal null, which is formed from ASCII characters. A null literal is always of the null type. --Link to documentation (Section 2.3)
Rather a circular sounding definition, but the value of null is the null reference itself - just another pointer. The value of the null reference isn't really relevant and is presumably up to the implementor, but zero or some other value that can't be confused with another object address is likely.
Confusion may be caused here because there is a character value called the null character with value \u0000. This is the default value for type char.
\u000 would be the unicode representation of a character with ASCII code 0, but has nothing to do with null as used by Java.
'\u0000'
decimal equivalent is 00
Char equivalent is NUL.
From Character in Javadoc: http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Character.html
static char MIN_VALUE
The constant value of this field is the smallest value of type char, '\u0000'.
This is the unicode value, that in CHAR is equivalent to NULL, ie it is the NULL CHARACTER, rather than being the literal NULL.
null is a literal and you can see the specification which says
in practice you can simply pretend that it's "merely a special literal that can be of any reference type".
as #assylias said what you read was surely not out of java :)

Categories