Why is the compiler able to determine the generic type parameter for an
assignment, but not for the ternary operator (?
)?
I have a question regarding the compiler being able to deduce the generic type
parameter in case of a "direct" assignment but failing in case of the ternary
operator (?
). My examples uses Guava's Optional
class, to make my point, but
I think the underlying issue is generic and not restricted to Optional
.
Optional
has a generic function absent()
:
public static <T> Optional<T> absent();
and I can assign an Optional<T>
to an Optional<Double>
:
// no compiler error
final Optional<Double> o1 = Optional.absent();
How does the compiler realize, that T
should be Double
in this case. Because
when using the ternary operator (?
), I need to tell the compiler specifically
to us Integer
as the generic parameter
// Type mismatch: cannot convert from Optional<capture#1-of ? extends Object> to Optional<Integer>
final Optional<Integer> o2 = true
? Optional.of(42)
: Optional.<Integer>absent();
otherwise I get the following error
Type mismatch: cannot convert from
Optional<capture#1-of ? extends Object>
toOptional<Integer>
Why is there a difference between a "direct" assignement and using the ternary operator? Or is there something else I am missing?
The actual type arguments of a generic type are. reference types, wildcards, or. parameterized types (i.e. instantiations of other generic types).
A class interface or a method that operates on a parameterized type is called generic, like generic class or generic method, and generics only works with objects. And their type differs based on their type arguments.
Generic MethodsA type parameter, also known as a type variable, is an identifier that specifies a generic type name. The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.
Because of type inference rules, it appears the ternary expression does not infer the type parameter from the return type. The type of the ternary expression depends on the types of its operands. But one of the operands has undetermined type parameter (Optional.absent()
). At that point the ternary expression still does not have a type, so it cannot influence the type parameter.
You can also look into this bug report for more information. You can look into the JLS .
The type of the conditional expression is the result of applying capture conversion (??5.1.10) to lub(T1, T2)
Here what the JLS says :
If the method result occurs in a context where it will be subject to assignment conversion to a type S, then let R be the declared result type of the method, and let R' = R[T1 = B(T1) ... Tn = B(Tn)] where B(Ti) is the type inferred for Ti in the previous section, or Ti if no type was inferred.
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