0

Is it safe and considered as a good practice to use directly the following comparison operators with Double wrapper class in Java: > , < , <= and >= ?

I've tried and it seems to work, as the following code:

Double tiny = 1.2;
Double big = 125.65;

System.out.println(tiny > big); 
System.out.println(tiny >= big);
System.out.println(tiny < big); 
System.out.println(tiny <= big); 

Produces this output:

false
false
true
true

Yet, as far as I know, Java does not support operator overloading and the official documention does not say a word about it, hence my question.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Mario
  • 99
  • 1
  • 10
  • 7
    The operators aren't overloaded. But the Doubles are unboxed before the comparison. What you have is fine, but be aware that if one of the Doubles is null, you'll have a NullPointerException. – JB Nizet Jun 21 '17 at 12:20

4 Answers4

2

From the language spec (with my own emphasis):

15.20.1. Numerical Comparison Operators <, <=, >, and >=

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).

Note that binary numeric promotion performs value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).

Where Sec 5.1.8 also says:

A type is said to be convertible to a numeric type if it is a numeric type (§4.2), or it is a reference type that may be converted to a numeric type by unboxing conversion.

So yes, it's fine to use wrapped primitives with numerical comparison operators; they're unboxed first.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • Thanks you :) I was aware of automatic boxing/unboxing for +, -, *, /, = operators, but as it is not the case for == (reference comparison) I was unsure. – Mario Jun 21 '17 at 12:32
  • Then perhaps you could have looked it up in the JLS, the same document that @Andy Turner looked up and cited, that is freely available online, and is arguably the first place anyone should go to answer such questions, given how useful documentation is? – Lew Bloch Jun 21 '17 at 14:03
2

It is as "safe" as using these operators with double values directly.

The compiler turns Double into double (and vice versa) where required; as the answer by Andy nicely describes.

The one thing to pay attention to: (un)boxing does not come for free. So assuming you are doing computations at high scale, you want to pay close attention to not accidentally use Double objects. Because constant (un)boxing can turn into a very real performance issue.

And to be really precise: unboxing is a pretty cheap operation; boxing is not.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 1
    It's nowhere near as much of a performance issue as boxing. It's just a call to `.doubleValue()`, for which the cost is non-zero, but pretty darn cheap. – Andy Turner Jun 21 '17 at 12:28
  • Sure. But he just dropped a small example. We don't know if he plans to create zillions of Double objects. Or worse, turn zillions of doubles into Doubles at some point, to then turn them back into doubles. Seen that, wasn't nice. But I enhanced my answer accordingly. – GhostCat Jun 21 '17 at 12:29
1

If the values differ in that range of your question you'll be fine. But with smaller values you may get some trouble with rounding problems:

System.out.println(0.3d * 3 == 0.9d); // -> false

So you may write some own methods to check if the difference is in an specified delta (only for ==) as

private boolean nearlyEqual(Double d1, Double d2, double delta) {
    if (d1 == null || d2 == null)
        return d1 == d2; // true if both null or return false (as specified)
    return Math.abs(d1 - d2) <= delta;
}
Stefan Warminski
  • 1,845
  • 1
  • 9
  • 18
  • That was my first thought too. But he is asking about **Double**, not **double** per se. – GhostCat Jun 21 '17 at 12:25
  • Thank you, by safe I meant "will not compare references" of Double wrapper class, the rounding issues are a problem with primitive types float and double – Mario Jun 21 '17 at 12:37
  • So they wouldn't apply to `Float` and `Double`, is that what you mean, @Mario? Because respectively they unbox to `float` and `double`, as folks explained. And rounding "issues" are a problem with programmers, not floating-point types. Floating point works exactly as documented. – Lew Bloch Jun 21 '17 at 14:07
0

In that case, the Java Compiler will do something called unboxing, which means it will convert your Double object class into primitive type:

https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

Regards