I have always heard (and thought of) Java as a strongly typed language. But only recently did I notice something that I have been using almost on a daily basis: int
and double
overloading.
I can write the following, and it is valid Java code:
int i = 1;
double j = 1.5;
double k = i + j;
But, if I have a method, one of whose arguments is a double
, I need to specify it:
public static <K, V> V getOrDefault(K k, Map<K, V> fromMap, V defaultvalue) {
V v = fromMap.get(k);
return (v == null) ? defaultvalue : v;
}
When I call the above method on a Map<String, Double>
, the defaultvalue
argument cannot be an int
:
getOrDefault(aString, aStringDoubleMap, 0); // won't compile
getOrDefault(aString, aStringDoubleMap, 0d); // compiles and runs just fine
Why does Java overload an int
to double
(just like it does in addition), and then autobox it to Double
? I think the answer lies in how Java does operator overloading (i.e. the overloading happens in the +
operator, and not from int
to double
), but I am not sure.
Here's hoping that SO can help me out on this.
That's because primitives don't work with generics. They need to be boxed.
For the invocation
getOrDefault(aString, aStringDoubleMap, 0); // won't compile
to work, Java would have to box the 0
to an Integer
, then somehow convert that to a Double
. That's not allowed by the language. It's similar to why you can't do
Double value = 3; // Type mismatch: cannot convert from int to Double
From the JLS, on invocation contexts
If the type of the expression cannot be converted to the type of the parameter by a conversion permitted in a loose invocation context, then a compile-time error occurs.
The type of the expression, 0
, an integer literal, is int
. Loose invocation contexts are defined as
Loose invocation contexts allow a more permissive set of conversions, because they are only used for a particular invocation if no applicable declaration can be found using strict invocation contexts. Loose invocation contexts allow the use of one of the following:
- an identity conversion (§5.1.1)
- a widening primitive conversion (§5.1.2)
- a widening reference conversion (§5.1.5)
- a boxing conversion (§5.1.7) optionally followed by widening reference conversion
- an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion
int
to Double
is not supported by any of those.
If you simply had
public static void main(String[] args) throws Exception {
method(3);
}
public static void method(double d) {
}
it would work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With