5

Can someone explain me why in the first case null pointer was detected, but no on the other ?

Maybe he always looks on the first type, but why he does so only if the condition is false..

@Test
public void test1() {
    final Integer a = null;

    final Integer b = false ? 0 : a;

    //===> NULL POINTER EXCEPTION
}

@Test
public void test2() {
    final Integer b = false ? 0 : null;

    //===>NOT NULL POINTER EXCEPTION
}

@Test
public void test3() {
    final Integer a = null;

    final Integer b = true ? 0 : a;

    //===>NOT NULL POINTER EXCEPTION
}

@Test
public void test4() {
    final Integer a = null;

    final Integer b = false ? new Integer(0) : a;

    //===> NOT NULL POINTER EXCEPTION
}

@Test
public void test5() {
    final Integer a = null;

    final Integer b = false ? a : 0;

    //===>NOT NULL POINTER EXCEPTION
}
Kimo_do
  • 568
  • 5
  • 12
  • Possible dupe: http://stackoverflow.com/questions/12763983/nullpointerexception-through-auto-boxing-behavior-of-java-ternary-operator (I don't vote to not close the question) –  Jun 29 '16 at 09:38
  • "If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T." so why test3 and test5 didn't thorw NPE? sorry i didn't get it – Kimo_do Jun 29 '16 at 10:27

2 Answers2

7

When you use ternary operator,

 flag  ? type1 : type2

Type1 and type2 must be of same type while conversion. First it realises type1 and then type2.

Now look at your cases

 final Integer b = false ? 0 : a;

Since type1 is 0 and it takes as a primitive and since a is trying to convert it as a primitive. Hence the null pointer.

where as same tricky test5

 final Integer b = false ? a : 0;

Since a is of type Integer 0 boxed to wrapper integer and assigned to the LHS.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 1
    This answer explains at a different level what the previous answer is saying. (the reason for `null.intValue()` being called. Good answer ;-) – Dylan Meeus Jun 29 '16 at 09:43
  • Thx for your answer, can you explain why test3 didn't throw NPE? why the conversion was not applied to the 'type1' so converting a to a primitive ? – Kimo_do Jun 29 '16 at 10:24
  • 1
    `final Integer b = true ? 0 : a;` Because the flag is true, it went to select 0. and the boxing happens to new Integer(0). Zero is a valid integer right? – Suresh Atta Jun 29 '16 at 14:46
  • the conversion happens to the true element not the first. I see ! thanks – Kimo_do Jun 29 '16 at 15:56
4

I think in this case a will unboxed to an int, because 0 is an int . That means that null.intValue() is called and get an NPE

@Test
public void test1() {
    final Integer a = null;

    final Integer b = false ? 0 : a;
Jens
  • 67,715
  • 15
  • 98
  • 113
  • well I am not sure that is the reason. How come that test4 does not throw an NPE then? – Dylan Meeus Jun 29 '16 at 09:35
  • The issue is that java interprets `a` as an int because of "?" –  Jun 29 '16 at 09:36
  • 1
    It will actually be *un*boxed to an `int`. But I'm wondering why test2 seems to box it, while test1 seems to unbox it... but @DylanMeeus, that's because nothing is called on the `null` in test 4, since no (un)boxing is done there. – Siguza Jun 29 '16 at 09:37
  • In test4 a in an interger, so also b will be interpreted as an Integer. – Jens Jun 29 '16 at 09:37
  • @Jens you are right. Running `javap -c` on the code shows that both `intValue()` and `valueOf()` are called ;-) Which is not the case for `test 4`. (As to answer my own question in the comments :P – Dylan Meeus Jun 29 '16 at 09:40
  • 1
    `If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.` - that's why test 2 works and test 1 fails. The `null` in test 2 is not unboxed, since it doesn't fulfill the quoted criteria (taken from the JLS). – Eran Jun 29 '16 at 09:43