2

In Java, there are wrapper objects which contains just a single primitive type. They are Integer, Double, Character, Boolean, Byte, Short, Long, Float, which boxes the int, double, char, boolean, byte, short, long, float primitive types respectively.

For most objects, they cannot be compared, but you can implement Comparable or Comparator so you can define when one object of a given type (call it Ty) is less, equal, or greater than another object of the same type Ty. However, if so, you test inequality by using compareTo(Ty oth) or compare(Ty arg0, Ty arg1), both returning int, representing less than if return value < 0, and vice versa.

However, for numeric Wrapper objects (including Character), you can actually compare these objects using inequality relational operators for primitives <, <=, >=, > as in this code below:

Integer a = 15;
Integer b = 0;
Double x = 7.5;
Double y = 15.000000000000000000000000001; // Decimal part discarded
Character ch = 'A';

System.out.println(x + " < " + a + " is " + (x < a));
System.out.println(x + " < " + b + " is " + (x < b));
System.out.println(a + " > " + b + " is " + (a > b));

System.out.println(ch + " <= " + 65 + " is " + (ch <= 64)); // 'A' has ASCII code 65
System.out.println(ch + " <= " + 65 + " is " + (ch <= 65));
System.out.println(a + " >= " + b + " is " + (a >= b));

Which outputs

7.5 < 15 is true
7.5 < 0 is false
15 > 0 is true
A <= 65 is false
A <= 65 is true
15 >= 0 is true

Note that between two objects, == and != always work and respectively denote reference equality and inequality instead. It is not part of the question.

Is "operator overloading" of these wrapper functions unique to the wrappers?

1 Answers1

2

First of all - a whole ratsnest of implications has been unveiled.

What is happening is that for the operators '>=', '<=', '<', and '>' the compiler already knows that they can only be executed on primitive types, so automatically an unboxing will happen (convert the Object type to a primitive type). That is why those operators can be executed on Integer instances.

However, when using '==' or '!=', the compiler knows it can compare instances directly, basically comparing wether or not two variables are referencing the same object or not. It is not a true integer comparison at all.

As a matter of fact, this will return false:

System.out.println("Test == :"+(new Integer(1000) == new Integer(1000)));
System.out.println("Test == :"+(new Integer(100) == new Integer(100)));

These most likely will return false:

System.out.println("Test == :"+((Integer)1000 == (Integer)1000));
System.out.println("Test == :"+(Integer.valueOf(1000) == Integer.valueOf(1000)));

Although these most likely will return true:

System.out.println("Test == :"+((Integer)100 == (Integer)100));
System.out.println("Test == :"+(Integer.valueOf(100) == Integer.valueOf(100)));

'Most likely' because it is going to be implementation specific, and even can be controlled by parameters.

due to the fact that integer objects with values in the range -127..128 are being interned when using the Integer.valueOf(int) static factory method. See a more elaborate explenation.

But please never assume that this will ever work, and always use the Comparable interface, .equals(...), or do the unboxing.

For reference, also review these articles:

YoYo
  • 9,157
  • 8
  • 57
  • 74
  • Can only Wrappers be unboxed? Also, == and != is not part of my question though since between objects (including wrappers) it means reference (in) equality – Ṃųỻịgǻňạcểơửṩ May 15 '18 at 00:12
  • There is a duality between primitive types and their boxed type (wrapper). You cannot extend that on other wrappers, because you can also not further define primitive types. – YoYo May 15 '18 at 00:14
  • 1
    If you use the constructor (instead of `Integer.valueOf`) you don't get the cached value. So both of your examples will always print false. – Bubletan May 15 '18 at 00:21
  • @Bubletan corrected based on your input - thx. – YoYo May 15 '18 at 00:38