4

I am comparing integer object with primitive int but getting null pointer exception if Integer object is null

public static void main(String[] args) {

        Integer a = null;
        int b = 1;

        if (a != b) {
            System.out.println("True");
        }

    }


Output : Exception in thread "main" java.lang.NullPointerException
    at com.nfdil.loyalty.common.Test.main(Test.java:10)

I am getting this because its trying to convert null integer object (a.intValue()) into primitive int.

Is there any other way to avoid this?

Shiladittya Chakraborty
  • 4,270
  • 8
  • 45
  • 94
  • 3
    This doesn't seem like a particularly close duplicate of the linked question, since this deals with Java's decision to perform comparisons by blind unboxing rather than via `Integer`-vs-`int` overload. – supercat Jun 11 '18 at 18:39

4 Answers4

7

You can use Objects.equals:

if (a == null || ! Objects.equals(a, b)) { ... }
Marco Sulla
  • 15,299
  • 14
  • 65
  • 100
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
  • 1
    This only works if the `a` is not `null`. If `a` is null and `b` is an `int` the `null == b` part of this function will throw a NPE. This only prevents executing `Object.equals(Object)` for null values. – csisy Mar 10 '21 at 10:19
  • @csisy that doesn't make any sense. how does comparing `null == b` thrown a NPE and why? to reassure you this code will not throw an exception. Also from the docs _Returns true if the arguments are equal to each other and false otherwise. Consequently, if both arguments are null, true is returned and **if exactly one argument is null, false is returned**. Otherwise, equality is determined by using the equals method of the first argument._. – Ousmane D. Mar 12 '21 at 10:16
  • here is an example code --> https://ideone.com/X1hAdz – Ousmane D. Mar 12 '21 at 10:20
  • You missed the point that `b` is **not** and `Integer` but an `int`. And it (the `null == b`) does throw an exception. Of course it's implementation detail how the `Objects.equals` is actually implemented. We use `adopt jdk 11` in which the `Objects.equals` is implemented by first comparing the two **objects** using the `==` operator. – csisy Mar 15 '21 at 13:02
  • 1
    @csisy See https://ideone.com/PvjfEb It doesn't seem to through an NPE. Even if b is an `int` – Dan Mar 21 '21 at 01:00
  • @Dan Yea, I've tried it as well in the linked online editor, that's why I thought that it might depend on the actual java lib used. For example, in our code base the `Objects.equals` first checks if `a == b` which throws a NPE if `a` is null and `b` is an int: https://ideone.com/oSDayv – csisy Mar 21 '21 at 11:43
3

Use if (a != null && a == b) to test of objects should be considered equal, or if (a == null || a != b) to test of objects should be considered unequal. Since b is an int rather than Integer it can't be null. Thus, if a is null it can't match b.

While one could convert b to an Integer and then use Object.equals() upon it, a literal interpretation of such code would ask the compiler and runtime to do a lot of needless work. While some versions of the JVM (runtime) might be able to recognize that one of the arguments to equals will always be a non-null Integer, and that it can thus skip a lot of the needless work and instead generate code equivalent to the if statement above, there's no guarantee that all versions would do so (and in fact, I would be very surprised if there weren't some versions that can't).

Incidentally, this approach will test the numerical value of a against b even if b happens to be numeric primitive type other than int [e.g. short, long or double]. Behavior when b is float might be a little unexpected [it compares b not with the number in a, but with the float value nearest to a], but when using long or double it will test for an exact numerical match. By contrast, approaches using equals would report that a was not equal to any number of any type other than int or Integer.

supercat
  • 77,689
  • 9
  • 166
  • 211
2

You can convert b to an Integer first and then compare with .equals:

Integer.valueOf(b).equals(a)
Robert Herhold
  • 384
  • 4
  • 18
  • 1
    There's no reason to convert `b` to an `Integer` before comparison. Simply use `if (a != null && a==b)` to test if things are equal, or `if (a == null || a != b)` to test if things are not equal. – supercat Jun 11 '18 at 18:37
  • @supercat Converting `b` to an `Integer` will always result in a non-`null` `Integer` object. This object's `equals(...)` method can then be used to safely compare it against other `Integer`s, whether the other `Integer` is null or not. That's the reason of converting `b` to an `Integer` for comparison. – Kröw Jun 11 '18 at 18:38
  • @Kröw: There already exist efficient operations to test whether `a` is null, and to test whether the `int` stored in a non-null `a` matches `b`, without having to create a new object on the heap or dispatch through a virtual `equals` method. Some versions of the JVM may be able to turn the code using `equals` into machine code that's as efficient as the code which manually handles the `null` case, but all should turn the code that manually handles `null` into efficient machine code. – supercat Jun 11 '18 at 18:42
  • @supercat Ok, but `Integer.valueOf(b).equals(a)` is more readable to me. There are multiple ways to solve some problems, and this answer is definitely a valid solution to this problem. I never said that this solution is better than the one you provided, or that it is worse. I simply gave the "reason to convert `b` to an `Integer` before comparison." There may exist more efficient solutions, but that doesn't stop this answer from being right. (Again, I prefer this for its readability.) If you have a working or better answer, feel free to post it. I'll upvote it if it's correct. – Kröw Jun 11 '18 at 18:53
  • @Kröw: I'd written an answer, but then the question got flagged as a duplicate. I see that it's since been unflagged. – supercat Jun 11 '18 at 18:58
1

For the sake of being able to compare the two, you can avoid this exception by casting b to an Integer.

Integer a = null;
int b = 0;
System.out.println(a != (Integer) b);

This will always result in true however, since a and (Integer) b evaluate each evaluate to different objects.

The reason that your original code threw an exception is because the JVM tried to convert a to an int. a had a value of null however, and the JVM can't convert that to an int. Casting the int to an Integer beforehand ensures that both of the compared terms are Integer objects so they can be compared normally, without the JVM having to do any unsafe implicit casting.

If you want to compare the numerical value of the two items, you could use an approach such as this:

Integer a = null;
int b = 0;
System.out.println(!((Integer) b).equals(a));
Kröw
  • 504
  • 2
  • 13
  • 31