java - relacionales - tipos de operadores en netbeans
¿Java no puede deducir el parámetro de tipo genérico al usar el operador ternario(`?`)? (2)
¿Por qué el compilador es capaz de determinar el parámetro de tipo genérico para una asignación, pero no para el operador ternario ( ?
)?
Tengo una pregunta con respecto al compilador que puede deducir el parámetro de tipo genérico en caso de una asignación "directa" pero falla en el caso del operador ternario ( ?
). Mis ejemplos usan la clase Optional
de Guava, para explicar mi punto, pero creo que el problema subyacente es genérico y no está restringido a Optional
.
Optional
tiene una función genérica absent()
:
public static <T> Optional<T> absent();
y puedo asignar un Optional<T>
Optional<Double>
a un Optional<Double>
:
// no compiler error
final Optional<Double> o1 = Optional.absent();
¿Cómo se da cuenta el compilador de que T
debería ser Double
en este caso? Porque cuando uso el operador ternario ( ?
), Necesito decirle al compilador específicamente a Integer
como el parámetro genérico
// 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();
de lo contrario me sale el siguiente error
No coincide el tipo: no se puede convertir desde la
Optional<capture#1-of ? extends Object>
Optional<capture#1-of ? extends Object>
aOptional<Integer>
¿Por qué hay una diferencia entre una asignación "directa" y el uso del operador ternario? ¿O hay algo más que me estoy perdiendo?
Debido a las reglas de inferencia de tipos, parece que la expresión ternaria no infiere el parámetro de tipo del tipo de retorno. El tipo de expresión ternaria depende de los tipos de sus operandos. Pero uno de los operandos tiene un parámetro de tipo indeterminado ( Optional.absent()
). En ese punto, la expresión ternaria todavía no tiene un tipo, por lo que no puede influir en el parámetro de tipo.
También puede consultar este informe de error para obtener más información. Puedes mirar en el JLS .
El tipo de expresión condicional es el resultado de aplicar la conversión de captura (?? 5.1.10) a lub (T1, T2)
Aquí lo que dice el JLS :
Si el resultado del método ocurre en un contexto en el que estará sujeto a la conversión de la asignación a un tipo S, entonces R será el tipo de resultado declarado del método y sea R ''= R [T1 = B (T1) ... Tn = B (Tn)] donde B (Ti) es el tipo inferido para Ti en la sección anterior, o Ti si no se infirió ningún tipo.
El problema es que el resultado del operador ternery se asigna a o2. El compilador no puede deducir el tipo a través de múltiples operaciones.
Básicamente creo que escribes la forma corta de:
Optional<?> tmp = true ? Optional.of(42): Optional.absent();
final Optional<Integer> o2 = tmp;
La conversión de la segunda línea es el problema.