Recentemente estou lendo o código-fonte do Spring Framework. Algo que não consigo entender vai aqui:
public Member getMember() {
// NOTE: no ternary expression to retain JDK <8 compatibility even when using
// the JDK 8 compiler (potentially selecting java.lang.reflect.Executable
// as common type, with that new base class not available on older JDKs)
if (this.method != null) {
return this.method;
}
else {
return this.constructor;
}
}
Este método é um membro da classe org.springframework.core.MethodParameter
. O código é fácil de entender, enquanto os comentários são difíceis.
NOTA: nenhuma expressão ternária para reter a compatibilidade JDK <8, mesmo quando usando o compilador JDK 8 (potencialmente selecionando
java.lang.reflect.Executable
como tipo comum, com essa nova classe base não disponível em JDKs mais antigos)
Qual é a diferença entre usar expressão ternária e usar if...else...
construção neste contexto?
fonte
Isso foi introduzido em um commit bastante antigo em 3 de maio de 2013, quase um ano antes do lançamento oficial do JDK-8. O compilador estava sob intenso desenvolvimento naquela época, então tais problemas de compatibilidade podiam ocorrer. Acho que a equipe do Spring acabou de testar a compilação do JDK-8 e tentou consertar os problemas, embora na verdade sejam problemas do compilador. No lançamento oficial do JDK-8, isso se tornou irrelevante. Agora, o operador ternário neste código funciona bem como esperado (nenhuma referência à
Executable
classe no arquivo .class compilado está presente).Atualmente, coisas semelhantes aparecem no JDK-9: algum código que pode ser bem compilado no JDK-8 falha com o JDK-9 javac. Acho que muitos desses problemas serão corrigidos até o lançamento.
fonte
Executable
, estava violando algum aspecto das especificações? Ou será que a Oracle percebeu que poderia mudar esse comportamento de uma forma que ainda estaria de acordo com as especificações e sem quebrar a compatibilidade com versões anteriores?Executable
tipo intermediário. Em Java-8, o conceito de inferência de tipo de expressão mudou drasticamente e esta parte foi completamente reescrita, portanto, não é tão surpreendente que as primeiras implementações tivessem bugs.A principal diferença é que um
if
else
bloco é uma instrução, enquanto o ternário (mais conhecido como o operador condicional em Java) é uma expressão .Uma instrução pode fazer coisas como
return
o chamador em alguns dos caminhos de controle. Uma expressão pode ser usada em uma atribuição:int n = condition ? 3 : 2;
Portanto, as duas expressões no ternário após a condição precisam ser coagíveis para o mesmo tipo. Isso pode causar alguns efeitos estranhos em Java, especialmente com a caixa automática e a conversão automática de referência - é a isso que o comentário em seu código postado se refere. A coerção das expressões no seu caso seria para um
java.lang.reflect.Executable
tipo (já que é o tipo mais especializado ) e que não existe nas versões anteriores do Java.Estilisticamente, você deve usar um
if
else
bloco se o código for semelhante a uma instrução e um ternário se for semelhante a uma expressão.Claro, você pode fazer um
if
else
bloco se comportar como uma expressão se usar uma função lambda.fonte
O tipo de valor de retorno em uma expressão ternária é afetado pelas classes pai, que mudaram conforme descrito em Java 8.
É difícil ver por que um elenco não poderia ter sido escrito.
fonte