You can simply use Apache Commons Lang:

result = ObjectUtils.compare(firstComparable, secondComparable)
Answer from Dag on Stack Overflow
🌐
LabEx
labex.io › tutorials › java-how-to-handle-integer-null-comparison-437111
How to handle Integer null comparison | LabEx
This tutorial explores comprehensive strategies for safely comparing Integer values, providing developers with essential techniques to prevent null pointer exceptions and write more robust code. In Java, null is a special literal that represents the absence of a value.
🌐
Reddit
reddit.com › r/learnprogramming › how do i compare a generic type with null in java?
r/learnprogramming on Reddit: How do I compare a generic type with null in java?
February 6, 2023 -

I've already discovered that comparing a generic type requires you to use an int to restore the value of compareTo, but if I'm trying to check if T value == Null, java throws an error stating that the compareTo (null) method is undefined for type T.

the code I have so far is

int cmp;
if(cmp = tree.get(index).compareTo(null) == 0)

to check if the value at the index of tree == null.

Thanks in advance :)

edit: well, I actually just fixed it by deleting cmp XD

Top answer
1 of 2
2
You’re probably doing it wrong; usually you want to use some method like contains to check whether something’s not in a collection, and compareTo(null) and equals(null) are bad mojo to begin with. Syntactically, Java’s complaining because it’s breaking the text down as if(cmp = (tree.….compareTo(null) == 0)) with tree.….compareTo(null) == 0 being assigned to cmp, and if testing the value that was assigned. But == 0 provides a boolean, not an int, so you can’t assign anything==anything to cmp; and then if expects a boolean or unboxed Boolean, not an int, so that’s also invalid. If you want to save compareTo’s result en passant, you need a pair of parens around the first part, if((cmp = tree.get(index).compareTo(null)) == 0) ↑here and here↑. Now the relational result from compareTo (an actual int) is saved to cmp, and that same value is compared against 0, producing a boolean for if to consume. Fundamentally, though, compareTo and equals describe bivalent relationships which break if you try to use null in there. For example, a.compareTo(b) represents a query of whether a ⋚ b, and therefore also whether b ⋛ a, and therefore any value of a should be able to be used in b’s place and vice versa. Similarly, a.equals(b) represents a query of whether a = b, and therefore also whether b = a. So let’s play with those identities. if(tree.get(index).compareTo(null) == 0) That looks just fine; we pass null as the argument to compareTo. But changing to the ostensibly-equivalent condition if(null.compareTo(tree.get(index)) == 0) is fully illegal; null doesn’t name a specific enough type to actually find a Comparable.compareTo implementation, and even if it were specific enough, that method would be given null for its this argument, which is illegal for non-static methods and must result in a NullPointerException being thrown. Similarly, if(tree.get(index).equals(null)) is syntactically valid, but if we flip it using the semantic identity, if(null.equals(tree.get(index))) we again have a problem: null would necessarily have an equals method if it named an object, but null contributes no vtable and thus no means of determining how to actually carry out equals’ execution. (Any type’s equals might be chosen with equal correctness, including the equals of an as-yet-nonexistent type.) And of course, trying to ((Foo)null).equals(…) would trigger a NullPointerException unless you’ve found your way to a static equals method. ( java.util.Objects ’ methods can be used when you really do want to involve null more safely in compareTo, equals, and other basic methods, although compare can still throw.) So what you almost always want is either the collections .contains or .containsKey method, which directly checks whether something’s in there, or if your collection is actually permitted to contain null (really don’t, because you can’t tell whether X{k}=null or k∉X), you want to == null or != null directly.
2 of 2
1
isNull() maybe?
🌐
Bug Database
bugs.java.com › bugdatabase › view_bug.do
Bug ID: JDK-6245437 (spec) Integer.compareTo(null) should document that it throws NPE
To reproduce it you may run following test: public class Test { public static void main(String[] args) { new Integer(3).compareTo(null); } } ---- the result is: Exception in thread "main" java.lang.NullPointerException ...
Top answer
1 of 7
145

The Short Answer

The key point is this:

  • == between two reference types is always reference comparison
    • More often than not, e.g. with Integer and String, you'd want to use equals instead
  • == between a reference type and a numeric primitive type is always numeric comparison
    • The reference type will be subjected to unboxing conversion
    • Unboxing null always throws NullPointerException
  • While Java has many special treatments for String, it is in fact NOT a primitive type

The above statements hold for any given valid Java code. With this understanding, there is no inconsistency whatsoever in the snippet you presented.


The Long Answer

Here are the relevant JLS sections:

JLS 15.21.3 Reference Equality Operators == and !=

If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.

This explains the following:

Integer i = null;
String str = null;

if (i == null) {   // Nothing happens
}
if (str == null) { // Nothing happens
}
if (str == "0") {  // Nothing happens
}

Both operands are reference types, and that's why the == is reference equality comparison.

This also explains the following:

System.out.println(new Integer(0) == new Integer(0)); // "false"
System.out.println("X" == "x".toUpperCase()); // "false"

For == to be numerical equality, at least one of the operand must be a numeric type:

JLS 15.21.1 Numerical Equality Operators == and !=

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible to numeric type, binary numeric promotion is performed on the operands. If the promoted type of the operands is int or long, then an integer equality test is performed; if the promoted type is float or double`, then a floating-point equality test is performed.

Note that binary numeric promotion performs value set conversion and unboxing conversion.

This explains:

Integer i = null;

if (i == 0) {  //NullPointerException
}

Here's an excerpt from Effective Java 2nd Edition, Item 49: Prefer primitives to boxed primitives:

In summary, use primitives in preference to boxed primitive whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations.

There are places where you have no choice but to use boxed primitives, e.g. generics, but otherwise you should seriously consider if a decision to use boxed primitives is justified.

References

  • JLS 4.2. Primitive Types and Values
    • "The numeric types are the integral types and the floating-point types."
  • JLS 5.1.8 Unboxing Conversion
    • "A type is said to be convertible to a numeric type if it is a numeric type, or it is a reference type that may be converted to a numeric type by unboxing conversion."
    • "Unboxing conversion converts [...] from type Integer to type int"
    • "If r is null, unboxing conversion throws a NullPointerException"
  • Java Language Guide/Autoboxing
  • JLS 15.21.1 Numerical Equality Operators == and !=
  • JLS 15.21.3 Reference Equality Operators == and !=
  • JLS 5.6.2 Binary Numeric Promotion

Related questions

  • When comparing two Integers in Java does auto-unboxing occur?
  • Why are these == but not equals()?
  • Java: What’s the difference between autoboxing and casting?

Related questions

  • What is the difference between an int and an Integer in Java/C#?
  • Is it guaranteed that new Integer(i) == i in Java? (YES!!! The box is unboxed, not other way around!)
  • Why does int num = Integer.getInteger("123") throw NullPointerException? (!!!)
  • Java noob: generics over objects only? (yes, unfortunately)
  • Java String.equals versus ==
2 of 7
16

Your NPE example is equivalent to this code, thanks to autoboxing:

if ( i.intValue( ) == 0 )

Hence NPE if i is null.

🌐
Medium
medium.com › @AlexanderObregon › javas-objects-compare-method-explained-7a9ccda5ea74
Java’s Objects.compare() Method Explained | Medium
December 13, 2024 - A positive integer if a is greater than b. Both Objects Are Null: If a and b are both null, the method considers them equal and returns 0.
Find elsewhere
Top answer
1 of 2
14

it is possible to handle null pointer exception using Comparator.comparing static method. If you want to comparing loanAmount fields in your objects and you want that every not null value is greater than null you can use Comparator.nullFirst method in combination with Comparator.comparing like the below code:

Comparator.comparing(LoanAccount::getLoanAmount,
                     Comparator.nullsFirst(Comparator.naturalOrder()))

NaturalOrder is a method returning a comparator that compares Comparable objects in natural order. You can also combine more comparators in a chain with method Comparator.thenComparing like the code below:

Comparator
        .comparing(LoanAccount::getLoanAmount,
                   Comparator.nullsFirst(Comparator.naturalOrder()))
        .thenComparing(LoanAccount::getCreationDate, 
                       Comparator.nullsFirst(Comparator.naturalOrder()))
        .compare(o1, o2);

Now you can rewrite your comparator with equal behaviour shortly:

public class LoanAccountAmountComparator
        implements Comparator<LoanAccount> {

    @Override
    public int compare(LoanAccount o1, LoanAccount o2) {
        if (o1 == null && o2 == null) return 0;
        if (o1 == null) return -1;
        if (o2 == null) return 1;
        return Comparator
                .comparing(LoanAccount::getLoanAmount,
                           nullsFirst(naturalOrder()))
                .thenComparing(LoanAccount::getCreationDate,
                               nullsFirst(naturalOrder()))
                .compare(o1, o2);
    }
}

Note: the use of class Date is discouraged, it is better if you use instead the java.time package classes for time related code.

2 of 2
7

Here is another twist, roughly similar to dariosicily's proposal.

It differs in the following points:

  • It create the aggregated comparator only once, then store it in a static field. Why? Because functions such as Comparator.nullsFirst() and Comparator.comparing() implies object allocation, which you definitely want to avoid if your comparator is called from tight loops (for example, a sort or tree insertion algorithm).
  • Null checks on the LoadAccount objects themselves have also been delegated to Comparator.nullsFirst(). That means that absolutely no if statement is required!
  • I moved that comparator to a public, static field of a utility class. I have learned from personal experience that comparators on domain model objects very often come in "families". In different places, you want different sorting strategies, for the same objects. Here, for demonstration, I also included one comparator for loadAmount (that is, without fallback on tie), and another one for creationDate. But you can see how this idea can be generalized.
  • In this sample, I have adopted an uncommon indentation strategy. I think this is justified in this case because it helps make it easier to see which fields are sorted by each comparator, and in which order. This is of great importance when you have comparators that involve a significant number of fields.
    public class LoanAccountAmountComparators {

        /**
         * A comparator that sort LoanAccounts, by load's amount, in decreasing order.
         */
        public static final Comparator<LoanAccount> BY_AMOUNT = 
            Comparator.nullsFirst(
                Comparator.comparing(
                    LoanAccount::getLoanAmount, Comparator.nullsFirst(Comparator.reverseOrder())
                );
            );

        /**
         * A comparator that sort LoanAccounts, by creation date, in ascending order.
         */
        public static final Comparator<LoanAccount> BY_DATE = 
            Comparator.nullsFirst(
                Comparator.comparing(
                    LoanAccount::getCreationDate, Comparator.nullsFirst(Comparator.naturalOrder())
                );
            );

        /**
         * A comparator that sort LoanAccounts, by creation amount (in descending order),
         * then by date (in ascending order).
         */
        public static final Comparator<LoanAccount> BY_AMOUNT_AND_DATE = 
            Comparator.nullsFirst(
                Comparator.comparing(
                    LoanAccount::getLoanAmount, Comparator.nullsFirst(Comparator.reverseOrder())
                ).thenComparing(
                    LoanAccount::getCreationDate, Comparator.nullsFirst(Comparator.naturalOrder())
                );
            );
    }

It should be noted that, in this example, all fields involved are indeed some kind of objects. If, however, your comparator would involve fields containing primitive types, then you should use the corresponding Comparator.comparing<primitiveType> function (that is, never let some primitive be boxed to object only so it can be compared to Comparator.naturalOrder().

🌐
GitHub
gist.github.com › hyamamoto › 6762765
Generic null safe " Comparable.compareTo()" implementations. · GitHub
Generic null safe " Comparable.compareTo()" implementations. ... Suuuuuuuggggggggggggggah. I've just wasted 5 min only to end up realizing the Guava also does the same thing smarter. But at least I made it Java 6 (GWT/Android) compatible...
🌐
Tutorialspoint
tutorialspoint.com › home › java/lang › java integer equals method
Java Integer equals Method
September 1, 2008 - The Java Integer equals() method compares this object to the specified object. The result is true if and only if the argument is not null and is an Integer object that contains the same int value as this object.
🌐
TutorialsPoint
tutorialspoint.com › comparing-strings-with-possible-null-values-in-java
Comparing Strings with (possible) null values in java?
import java.util.Scanner; public class CompringStrings { public static void main(String args[]) { Scanner sc = new Scanner(System.in); System.out.println("Enter your first string value: "); String str1 = sc.next(); System.out.println("Enter your second string value: "); String str2 = sc.next(); //Comparing two Strings int res = str1.compareTo(str2); System.out.println(res); if(res==0) { System.out.println("Both Strings are null or equal"); }else if(res<0){ System.out.println(""+str1+" preceeds "+str2+""); }else if(res>0){ System.out.println(""+str2+" preceeds "+str1+""); } } } Enter your first string value: null Enter your second string value: null 0 Both Strings are null or equal
🌐
Baeldung
baeldung.com › home › java › java numbers › check if an integer value is null or zero in java
Check if an Integer Value Is Null or Zero in Java | Baeldung
January 8, 2024 - Using the logical OR operator could be the first idea to perform the check. It simply checks if the given Integer number is null or zero.
Top answer
1 of 11
414

No, == between Integer, Long etc will check for reference equality - i.e.

Integer x = ...;
Integer y = ...;

System.out.println(x == y);

this will check whether x and y refer to the same object rather than equal objects.

So

Integer x = new Integer(10);
Integer y = new Integer(10);

System.out.println(x == y);

is guaranteed to print false. Interning of "small" autoboxed values can lead to tricky results:

Integer x = 10;
Integer y = 10;

System.out.println(x == y);

This will print true, due to the rules of boxing (JLS section 5.1.7). It's still reference equality being used, but the references genuinely are equal.

If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1), or the boolean literal true or false (§3.10.3), or a character literal between '\u0000' and '\u007f' inclusive (§3.10.4), then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.

Personally I'd use:

if (x.intValue() == y.intValue())

or

if (x.equals(y))

As you say, for any comparison between a wrapper type (Integer, Long etc) and a numeric type (int, long etc) the wrapper type value is unboxed and the test is applied to the primitive values involved.

This occurs as part of binary numeric promotion (JLS section 5.6.2). Look at each individual operator's documentation to see whether it's applied. For example, from the docs for == and != (JLS 15.21.1):

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).

and for <, <=, > and >= (JLS 15.20.1)

The type of each of the operands of a numerical comparison operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs. Binary numeric promotion is performed on the operands (§5.6.2). If the promoted type of the operands is int or long, then signed integer comparison is performed; if this promoted type is float or double, then floating-point comparison is performed.

Note how none of this is considered as part of the situation where neither type is a numeric type.

2 of 11
51

Since Java 1.7 you can use Objects.equals:

java.util.Objects.equals(oneInteger, anotherInteger);

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.

🌐
Blogger
javahungry.blogspot.com › 2021 › 12 › check-if-int-is-null-in-java.html
Check if an int is a null in Java | Java Hungry
public class CheckIfIntIsNull { public static void main(String args[]) { // Integer primtive data type int empId = 23; // Integer wrapper class Integer empId2 = new Integer(34); System.out.println("Primitive int empId is: "+ empId); System.out.println("Wrapper class Integer object is: "+ empId2); /* Can not check for null property for int, We can check for null property for Integer */ if (empId2 == null) { System.out.println("Integer wrapper class object is NULL"); } else { System.out.println("Integer wrapper class object is NOT NULL"); } } } Output: Primitive integer empId is: 23 Wrapper clas
🌐
GeeksforGeeks
geeksforgeeks.org › java › java-integer-compareto-method
Java Integer compareTo() method - GeeksforGeeks
April 3, 2023 - public int compareTo(Integer anotherInt) Parameter : anotherInt- : the Integer to be compared. Return : - This method returns the value 0 if this Integer is equal to the argument Integer; - a value less than 0 if this Integer is numerically less than the argument Integer; - and a value greater than 0 if this Integer is numerically greater than the argument Integer (signed comparison). Example 01 : To show working of java.lang.Integer.compareTo() method.