sl311
asked on
Null Pointer on conditional initialisation with a method call
Hi,
Given the following code, why on the last initialisation of variable "f" do I get a NullPointerException? The examples before, "a-e" seem to indicate there shouldn't be a problem with it.
Integer a = true?1:2;
Integer b = false?1:2;
Integer c = getTest();
Integer d = true?1:getTest();
Integer e = false?1:null;
Integer f = false?1:getTest();
Where getTest is:
private Integer getTest() {
return null;}
Given the following code, why on the last initialisation of variable "f" do I get a NullPointerException? The examples before, "a-e" seem to indicate there shouldn't be a problem with it.
Integer a = true?1:2;
Integer b = false?1:2;
Integer c = getTest();
Integer d = true?1:getTest();
Integer e = false?1:null;
Integer f = false?1:getTest();
Where getTest is:
private Integer getTest() {
return null;}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
h fails for the same reasons as f. g works because you explicitely tell it to use an Integer object.
I totally agree with you that it's not logical to unbox/box in sequence, but there probably is a technical reason for this in the compiler or VM.
You should read up on the conditional operator (15.25) and binary numeric promotion (5.6.2) in the language spec:
http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html
I totally agree with you that it's not logical to unbox/box in sequence, but there probably is a technical reason for this in the compiler or VM.
You should read up on the conditional operator (15.25) and binary numeric promotion (5.6.2) in the language spec:
http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html
actually this is not because of autoboxing but because of the optimization done by compiler!
the compiler understand the code/staement Integer f = false?1:getTest(); and thinks that it is inefficient! So it compiles that code into a optimized way as below,
Integer f = Integer.valueOf(getTest(). intValue() );
so that it can avoid the unnecessary checking at runtime!
Integer f = Integer.valueOf(getTest().
so that it can avoid the unnecessary checking at runtime!
in case of Integer d = true?1:getTest();
it will be compiled as Integer d = Integer.valueOf(1);
it will be compiled as Integer d = Integer.valueOf(1);
ASKER
I think it might be compiled like that because I've used true or false in my examples - in reality these would be determined at run time, so the autoboxing and conditional operator mentioned in Bart CR's links are the reason for this behaviour.
Still seems wrong to me (what if I have subclassed Integer to MyInteger for example - by going through this MyInteger -> int -> MyInteger process it would lose any extra information that method had put onto MyInteger)
At least I know now - thankyou for your help. I've changed the original problematic line to:
Integer f = false?(Integer)1:getTest() ;
And it seems to work fine.
Still seems wrong to me (what if I have subclassed Integer to MyInteger for example - by going through this MyInteger -> int -> MyInteger process it would lose any extra information that method had put onto MyInteger)
At least I know now - thankyou for your help. I've changed the original problematic line to:
Integer f = false?(Integer)1:getTest()
And it seems to work fine.
>>what if I have subclassed Integer to MyInteger
you can't becuase the wrappers( Integer, Double... ) are final!
you can't becuase the wrappers( Integer, Double... ) are final!
ASKER
So the "?" operator checks the return type of BOTH possible values, and if EITHER is an "int", it will pass any Integer to an int before autoboxing again to an Integer ? The following seems to confirm this (g works, h fails)
Integer g=false?new Integer(1):getTest();
Integer h=true?getTest():1;
That doesn't seem a very logical way to apply autoboxing to the "?" operator - wouldn't it be better to apply autoboxing to the return value only if it needs it ?
Unnecessarily doing an Integer -> int -> Integer conversion will take extra time, and causes the failure of what looks like a reasonable statement.