¿Por qué en la primera línea principal no tira ClassCastException mientras que el segundo lo hace?
import java.util.function.Function;
class Scratch {
static <T> T getSomething(Function<Integer, T> fun) {
return (T) fun;
}
public static void main(String[] args) {
Scratch.<String>getSomething(x -> "hello");
String something = Scratch.<String>getSomething(x -> "hello");
}
}
La diferencia se debe a que no se utiliza el resultado del método en el primer caso, pero lo hace en el segundo.
Un molde es una expresión , pero no es una StatementExpression
. Esto significa que no se puede escribir lo siguiente:
(String) somethingReturningAString();
pero se puede escribir:
String aString = (String) somethingReturningAString();
En tiempo de compilación, las inserciones del compilador checkcast
instrucciones donde debe, y donde se puede:
- No puede insertar un molde para el primer caso, por lo que no se lleva a cabo la comprobación.
- Se puede (y debe) insertar un molde en el segundo caso, con el fin de asegurarse de que está asignando algo que es en realidad una
String
a unaString
variable. Como tal, se comprueba el reparto, y que falla.
Vale la pena señalar que hay algunos casos tal vez inesperados, donde un elenco no es estrictamente necesario, pero se inserta. Por ejemplo:
Scratch.<String>getSomething(x -> "hello").toString();
fallaría con una ClassCastException
, ya que se transforma en:
((String) Scratch.getSomething(x -> "hello")).toString();
a pesar de que Object
tiene un toString()
método, y por lo que podría invocar que sin una conversión.