Récemment, je lis le code source de Spring Framework. Quelque chose que je ne peux pas comprendre va ici:
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;
}
}
Cette méthode fait partie de la classe org.springframework.core.MethodParameter
. Le code est facile à comprendre tandis que les commentaires sont difficiles.
REMARQUE: aucune expression ternaire pour conserver la compatibilité JDK <8 même lors de l'utilisation du compilateur JDK 8 (éventuellement en sélectionnant
java.lang.reflect.Executable
comme type commun, avec cette nouvelle classe de base non disponible sur les anciens JDK)
Quelle est la différence entre l'utilisation d'une expression ternaire et l'utilisation d'une if...else...
construction dans ce contexte?
la source
Cela a été introduit dans un commit assez ancien le 3 mai 2013, presque un an avant la sortie officielle du JDK-8. Le compilateur était en cours de développement intensif à cette époque, de tels problèmes de compatibilité pouvaient donc survenir. Je suppose que l'équipe Spring vient de tester la version JDK-8 et a essayé de résoudre les problèmes, même s'il s'agit en fait de problèmes de compilateur. À la sortie officielle du JDK-8, cela est devenu hors de propos. Maintenant, l'opérateur ternaire dans ce code fonctionne correctement comme prévu (aucune référence à
Executable
classe dans le fichier .class compilé n'est présente).Actuellement, des choses similaires apparaissent dans JDK-9: certains codes qui peuvent être bien compilés dans JDK-8 échouent avec JDK-9 javac. Je suppose que la plupart de ces problèmes seront résolus jusqu'à la sortie.
la source
Executable
, violait certains aspects des spécifications? Ou est-ce simplement qu'Oracle s'est rendu compte qu'il pouvait changer ce comportement d'une manière qui serait toujours conforme à la spécification et sans rompre la compatibilité descendante?Executable
taper entre les deux. En Java-8, le concept d'inférence de type d'expression a radicalement changé et cette partie a été complètement réécrite, il n'est donc pas si surprenant que les premières implémentations aient des bogues.La principale différence est qu'un
if
else
bloc est une instruction tandis que le ternaire (plus souvent appelé opérateur conditionnel en Java) est une expression .Une instruction peut faire des choses comme
return
à l'appelant sur certains des chemins de contrôle. Une expression peut être utilisée dans une affectation:int n = condition ? 3 : 2;
Ainsi, les deux expressions dans le ternaire après la condition doivent être forcées au même type. Cela peut provoquer des effets étranges en Java, en particulier avec l'auto-boxing et le casting de référence automatique - c'est à cela que fait référence le commentaire dans votre code publié. La contrainte des expressions dans votre cas serait un
java.lang.reflect.Executable
type (car c'est le type le plus spécialisé ) et qui n'existe pas dans les anciennes versions de Java.Stylistiquement, vous devez utiliser un
if
else
bloc si le code ressemble à une instruction et un ternaire s'il ressemble à une expression.Bien sûr, vous pouvez faire en sorte qu'un
if
else
bloc se comporte comme une expression si vous utilisez une fonction lambda.la source
Le type de valeur de retour dans une expression ternaire est affecté par les classes parentes, qui ont changé comme décrit dans Java 8.
Difficile de voir pourquoi un casting n'aurait pas pu être écrit.
la source