Pourquoi le “final” n'est pas autorisé dans Java 8 méthodes d'interface?
L'une des caractéristiques les plus utiles de Java 8 sont les nouveaux default
méthodes sur les interfaces. Il y a essentiellement deux raisons (il peut y en avoir d'autres) pourquoi ils ont été introduits:
- De donner des implémentations par défaut. Exemple:
Itérateur.remove()
- Permettant de l'API du JDK évolution. Exemple:
Itératif.forEach()
À partir d'une API designer point de vue, j'aurais aimé être capable d'utiliser d'autres modificateurs sur les méthodes d'interface, par exemple final
. Cela peut être utile lors de l'ajout de méthodes pratiques, la prévention "accidentelle" remplace dans la mise en œuvre des classes:
interface Sender {
//Convenience method to send an empty message
default final void send() {
send(null);
}
//Implementations should only implement this method
void send(String message);
}
Ci-dessus est déjà pratique courante si Sender
étaient une classe:
abstract class Sender {
//Convenience method to send an empty message
final void send() {
send(null);
}
//Implementations should only implement this method
abstract void send(String message);
}
Maintenant, default
et final
sont évidemment contradictoires mots-clés, mais le mot clé default lui-même n'aurait pas été strictement nécessaire, donc je suis en supposant que cette contradiction est délibérée, afin de refléter les différences subtiles entre "les méthodes de la classe avec le corps" (juste des méthodes) et "méthodes d'interface avec le corps" (méthodes par défaut), c'est à dire les différences qui je n'ai pas encore compris.
À un certain point, de temps, de soutien pour les modificateurs comme static
et final
sur les méthodes d'interface n'est pas encore totalement exploré, citant Brian Goetz:
L'autre partie est de savoir jusqu'où nous allons aller à la classe de soutien-bâtiment
outils d'interfaces, telles que la finale de méthodes, les méthodes privées, protégées
des méthodes, des méthodes statiques, etc. La réponse est: nous ne savons pas encore
Depuis ce temps, à la fin de 2011, à l'évidence, le soutien pour static
méthodes des interfaces a été ajouté. Clairement, cela ajoute beaucoup de valeur à la JDK les bibliothèques elles-mêmes, comme avec Comparateur.comparer()
.
Question:
Quelle est la raison final
(et aussi static final
) n'a jamais fait de Java 8 interfaces?
- Hmmm... vous (ou quelqu'un avec le même nom que vous) semblent donner au moins une raison possible dans le lien citant Brian Goetz. Serait-il? Mais au-delà, je n'ai aucune idée. Je ne suis pas près de suffisamment d'expérience pour être poster dans le développement java listes de diffusion.
- C'était moi. Mais je n'ai pas donné la réponse, j'ai seulement posé la question il y a déjà longtemps 🙂 Mais j'ai promis de Brian Goetz de ne pas déranger le lambda-dev liste de diffusion de plus avec cette demande, et puis j'ai perdu la trace de cette discussion particulière.
- Je vois... +1 pour la question intéressante. Ce serait bien si l'un de ces designers, ont montré jusqu'à répondre à cette question. Je suppose que l'affichage de la liste de diffusion à propos de ce n'est pas exactement encouragé...
- Merci pour le soutien. En fait, j'ai déjà discuté de cette question en particulier (et celui-ci) avec Brian Goetz dans un Courriel privé conversation. Il m'a demandé de soulever la question publiquement, pour la communauté de profiter de ces choses. Les Chances sont, il va donner une réponse faisant autorité de lui-même.
- Oh c'est intéressant! Ne peut pas attendre pour obtenir une réponse.
- Je suis désolé de jouer les trouble-fête, mais la seule façon de la question exprimée dans le titre va obtenir une réponse dans les termes de l'est DONC par une citation de Brian Goetz ou la JSR groupe d'Experts. Je comprends que BG a demandé un débat public, mais c'est exactement ce qui enfreint les conditions de la SORTE, comme il l'est principalement par opinion'. Il me semble que les responsabilités sont en train de disparaître ici. C'est l'Expert du Groupe de travail, et l'ensemble de la Communauté Java du Processus, afin de stimuler la discussion et de trouver des justifications. Pas SI de la. Donc je vote pour fermer comme "principalement par opinion'.
- Comme nous le savons tous,
final
empêche une méthode d'être remplacé, et de voir comment vous DEVEZ remplacer les méthodes héritées d'interfaces, je ne vois pas pourquoi il serait logique de le rendre définitif. Sauf si c'était pour signifier que la méthode est définitive qu'APRÈS l'impérieuse d'une fois.. Dans ce cas, peut-être qu'il qas difficultés? Si je ne suis pas la compréhension de ce droit, s'il vous plaît laissez-moi kmow. Semble intéressant - Comme un membre important de la communauté, vous pouvez creuser des lambda-dev mails pour donner également une réponse faisant autorité. Ce qui s'est passé sur l'avant. Notez que Brian Goetz n'a pas demande un débat public. Il a demandé à un public Q&A. de La discussion et de la justification a longtemps été donné, mais il est caché dans les listes de diffusion qui ne sont pas bien référencé dans les recherches Google. Avoir une réponse faisant autorité ici serait en fait plus d'augmenter la qualité d'une plate-forme très utile.
- Si je peux le faire, si vous le pouvez, et de répondre à votre propre question, qui n'a pas eu besoin de demander. Vous semblez d'accord avec moi que toute "réponse faisant autorité" doit venir de la par exemple, dans le cas le 'public Q&A' une partie de ce perd toute pertinence.
- "Si je peux le faire, si vous le pouvez, et de répondre à votre propre question, qui n'a pas eu besoin de demander." Qui s'appliquerait assez bien à toutes les questions sur ce forum, non? Je pourrais toujours Google un certain sujet pour 5 heures de moi-même et d'apprendre quelque chose que tout le monde a à apprendre le tout aussi dure. Ou nous attendre pour un autre couple de minutes pour quelqu'un de donner une meilleure réponse que tout le monde dans l'avenir (y compris les 12 upvotes et 8 étoiles jusqu'à présent) peut en profiter, parce que tant est si bien référencé sur Google. Donc, oui. Cette question peut parfaitement s'insérer dans de SORTE Q&Un formulaire.
- Faire de votre esprit. L'éther, vous vous demandez SI les membres de chalutage par le biais de la liste de diffusion pour vous, ce qui est un hors-sujet demande pour un hors-site de ressources ou de demander un 'public Q&A', auquel cas il est principalement opinion'. Dans les deux cas, il est hors-sujet, mais intéressant.
- comment vous DEVEZ remplacer les méthodes héritées d'interfaces..." ce n'est pas vrai dans Java 8. Java 8 permet de mettre en œuvre des méthodes dans les interfaces, ce qui signifie que vous n'avez pas à les mettre en œuvre dans la mise en œuvre des classes. Ici,
final
aurait une utilisation dans la prévention de la mise en œuvre de classes de remplacer la valeur par défaut de la mise en œuvre d'une méthode d'interface. - Vous et moi avons été sur cette plate-forme depuis assez longtemps pour savoir que parfois, il était intéressant, et sur-rubrique questions que la personne qui pose la question pourrait ont répondu eux-mêmes. En fait, encore une fois, cela est vrai pour à peu près chaque question. Exemple: "Comment voulez-vous faire ceci et cela avec XSLT?" - "Oh, après 10h de l'expérimentation (par exemple Google), j'ai tout compris moi-même." 🙂 Je suis heureux de continuer à en discuter sur meta...
- eh bien tout simplement il y a quelques jours, j'ai besoin de quelques
default final
méthodes, et a constaté qu'ils ne sont pas autorisés:( je ne vois pas de solides arguments à l'encontre de la combinaison. - La déclaration d'une
default
méthodefinal
impliquerait que les classes de mise en œuvre de deux interfaces avec la même méthode, n'ont aucune chance de lever l'ambiguïté... d'autre part je ne vois aucune raison pratique pour interdire remplacement d'une méthode de convenance comme dans l'exemple. Il pourrait ne pas être destiné à être remplacé, mais le remplacement ne fait pas de mal. Hey, je suis en attente pour le côté “je veux traiter les interfaces des classes comme” discussion: “qu'en est-il de la visibilité quepublic
pourinterface
méthodes?”. - Comme on peut le voir dans la cité de discussion, la visibilité de discussion est étroitement liée à la discussion sur les autres outils de construction, comme
final
. Malheureusement, ma référence n'est pas très à jour. Il doit y ai été plus récentes discussions concernantfinal
. Aussi loin que le multi-héritage des conflits sont concernés, nous avons déjà ces. Considérer:interface A1 { void x(); }
etinterface A2 { int x(); }
. Ouinterface B1 extends List<Object> {}
etinterface B2 extends List<String> {}
- ... de toute façon, je ne cherche pas un autre argument sur ce que devrait ou pourrait l'ai fait, je suis simplement curieux de savoir exactement pourquoi il a été décidé de la façon dont il est.
- vous ne savez jamais: Brian Goetz peut répondre!
- Et en effet il l'a fait, et qui peut avoir été l'intention d'origine, auquel cas mes commentaires ne s'appliquent pas. Mais si elle a l'intention d'origine, il doit avoir été clairement dit. Sinon, la question semble juste comme une opinion-collector.
- final est un poison. Si vous essayez de plier quelqu'un d'autre bibliothèque, il est dans la manière.
- Pour faire un cas où la finale est bénéfique dans l'interface par défaut des méthodes est l'utilisation de variadic listes d'arguments. Pour le moment, il n'est pas possible d'avoir un variadic liste d'arguments dans une méthode de l'interface sans avertissement. Une dernière méthode par défaut serait de faire de telles interfaces beaucoup plus pratique:
public interface A<T> { void add(T e); @safeVarArgs default final void addAll(T... elems) { for (T e : elems) add(e); }}
à Cause finale et, par conséquent, @safeVarArgs n'est pas autorisé ici, on a: "Type de sécurité: Potentiel tas de pollution par varargs paramètre elems"
Vous devez vous connecter pour publier un commentaire.
Cette question est, dans une certaine mesure, liée à Quelle est la raison pour laquelle le “synchronisé” n'est pas autorisé dans Java 8 méthodes d'interface?
La chose à comprendre au sujet des méthodes par défaut, c'est que le but premier de la conception est évolution de l'interface, à ne pas "tourner interfaces dans (médiocre) des traits". Bien qu'il y ait un certain chevauchement entre les deux, et nous avons essayé d'être accueillant pour la dernière où il n'a pas obtenir de la manière de l'ancien, ces questions sont mieux compris lorsqu'ils sont affichés dans cette lumière. (Remarque aussi que les méthodes de la classe sont va être différent de méthodes d'interface, quelle que soit l'intention, en vertu du fait que les méthodes d'interface peut être multiplier hérité.)
L'idée de base d'une méthode par défaut est: c'est une méthode d'interface avec un défaut de mise en œuvre, et une classe dérivée peut fournir plus spécifiques de mise en œuvre. Et parce que le centre de design a évolution de l'interface, il était un critique objectif de la conception que les méthodes par défaut pourra être ajouté à des interfaces après le fait dans une source compatible et compatible au niveau binaire manière.
Le trop-simple réponse à "pourquoi ne pas finale méthodes par défaut" c'est qu'alors le corps serait alors de ne pas être tout simplement le défaut de mise en œuvre, il serait le seul de la mise en œuvre. Alors que c'est un peu trop simple d'y répondre, il nous donne un indice que la question est déjà en route dans une douteuse direction.
Une autre raison pourquoi interface finale méthodes sont discutables, c'est qu'ils impossible de créer des problèmes pour les développeurs. Par exemple, supposons que vous avez:
Ici, tout est bon;
C
héritefoo()
deA
. Maintenant, supposezB
est modifié pour avoir unfoo
méthode, avec une valeur par défaut:Maintenant, quand nous allons à recompiler
C
, le compilateur va nous dire qu'il ne sait pas ce comportement d'hériter defoo()
, doncC
a remplacer (et peut choisir de déléguer àA.super.foo()
si elle voulait conserver le même comportement.) Mais que faire siB
avait fait de son défautfinal
, etA
n'est pas sous le contrôle de l'auteur deC
? MaintenantC
est irrémédiablement cassé; il ne peut pas compiler sans écraserfoo()
, mais il ne peut pas remplacerfoo()
si elle était définitive dansB
.C'est juste un exemple, mais le point est que la finalité de méthodes est vraiment un outil qui fait plus de sens dans le monde de l'unique héritage de classes (généralement en couple état pour le comportement), que pour les interfaces qui contribuent simplement le comportement et peut être multiplier hérité. C'est trop dur à raison à propos de "ce que les autres interfaces peut être mélangé dans l'éventuelle réalisateur", et en permettant à une méthode d'interface final serait probablement la cause de ces problèmes (et ils le feraient sauter pas sur la personne qui a écrit l'interface, mais sur les pauvres de l'utilisateur qui tente de la mettre en œuvre.)
Une autre raison pour les interdire, c'est qu'ils ne serait pas dire ce que vous pensez qu'ils veulent dire. Un défaut de mise en œuvre est prise en compte uniquement si la classe (ou de ses super-classes) ne pas fournir une déclaration (concrète ou abstraite) de la méthode. Si une méthode par défaut ont été finale, mais une super-classe déjà mis en œuvre la méthode, la valeur par défaut sera ignoré, ce qui n'est probablement pas ce que la valeur par défaut de l'auteur m'attendais lors de la déclaration définitive. (Ce comportement de l'héritage est un reflet de la conception du centre des méthodes par défaut -- évolution de l'interface. Il devrait être possible d'ajouter une valeur par défaut de la méthode (ou un défaut de mise en œuvre à une méthode d'interface) pour les interfaces existantes qui ont déjà mises en œuvre, sans changer le comportement de l'existant des classes qui implémentent l'interface, afin de garantir que les classes qui ont déjà travaillé avant le défaut méthodes ont été ajoutées fonctionnera de la même manière en présence de méthodes par défaut.)
default
méthodes l'utilisation si la classe abstraite et l'interface est en train de devenir floue. Je peux donc dire que ledefault
méthodes sont là pour assurer la compatibilité descendante w.r.t. l'interface et les classes abstraites pour squelettique mise en œuvre des méthodes parmi les classes ceux étendre la classe abstraite.Dans le lambda liste de diffusion il y a beaucoup de discussions à ce sujet. L'un de ceux qui semble contenir beaucoup de discussions à propos de tout ça est la suivante: Sur Variée la méthode de l'interface de la visibilité (a Final défenseurs).
Dans cette discussion, Talden, l'auteur de la question d'origine demande quelque chose de très similaire à votre question:
Finalement Brian Goetz réponse était:
Donc, très probablement, il n'a jamais été mis en œuvre parce qu'il n'a jamais fait partie de la portée. Il n'a jamais été proposé dans les délais prévus.
Dans une autre discussion animée à propos de final défenseur des méthodes sur le sujet, Brian a dit de nouveau:
Donc cela renforce ma théorie qu'il n'était tout simplement pas partie de la portée ou de la partie de leur conception. Ce qu'ils ont fait était de fournir suffisamment de fonctionnalités pour traiter les problèmes de l'API de l'évolution.
Il sera difficile de trouver et d'identifier des "LA" réponse, pour les resons mentionné dans les commentaires de @EJP : Il y a environ 2 (+/- 2) personnes dans le monde qui peut donner la réponse définitive à tous les. Et dans le doute, la réponse est peut-être juste quelque chose comme "le Soutien de finale par défaut méthodes ne semblent pas être la valeur de l'effort de restructuration de l'appel interne des mécanismes de résolution". C'est de la spéculation, bien sûr, mais il est au moins soutenus par des preuves, à l'instar de ce Déclaration (par l'une des deux personnes) dans le OpenJDK liste de diffusion:
et les faits banals comme une méthode n'est tout simplement pas considéré comme d'être (vraiment) méthode finale quand c'est un
default
méthode, tel qu'il est actuellement mis en œuvre dans le Méthode: is_final_method méthode dans l'OpenJDK.Plus vraiment "faisant autorité" de l'information est en effet difficile à trouver, même avec un nombre excessif de websearches et par la lecture de journaux. J'ai pensé qu'il pourrait être lié à des ambiguïtés potentielles lors de la résolution de la méthode de l'interface des appels avec le
invokeinterface
instruction et de classe et les appels de méthode, correspondant à lainvokevirtual
instruction: Pour lainvokevirtual
instruction, il y a peut être un simple vtable de recherche, parce que la méthode doit être hérité d'une super-classe, ou mis en œuvre par la classe directement. En revanche, uneinvokeinterface
appel doit examiner le site d'appel respective pour en savoir qui interface de cet appel, désigne en fait (ceci est expliqué plus en détail dans la InterfaceCalls page du HotSpot Wiki). Cependant,final
méthodes ne soit pas obtenir insérée dans l' vtable à tous, ou remplacer les entrées existantes dans la vtable (voir klassVtable.cpp. Ligne 333), et de même, les méthodes par défaut sont en train de remplacer les entrées existantes dans la vtable (voir klassVtable.cpp Ligne 202). Ainsi, le réelle raison (et donc, de la réponse) doit être cachée plus profond à l'intérieur de l' (assez complexe) appel de la méthode des mécanismes de résolution, mais peut-être que ces références seront néanmoins être considérée comme étant utile, ne serait-ce que pour les autres qui parviennent à tirer la réelle réponse.int
s, voir stackoverflow.com/questions/430346 ... ...synchronized
surdefault
méthodes.final
question, et c'est un peu humiliant que personne d'autre ne semblait penser à des exemples similaires (ou, peut-être, certains ont cru à propos de ces exemples, mais ne pas se sentir faisant autorité suffisante pour répondre). Alors maintenant, le (désolé, j'ai pour ce faire: ) final parole.Je ne pense pas qu'il est nécessaire de spécifier
final
sur un convienience la méthode de l'interface, je peux convenir cependant qu'il peut être utile, mais apparemment les coûts ont emporte sur les avantages.Ce que vous êtes censé faire, de toute façon, c'est écrire des bon javadoc pour la méthode par défaut, montrant exactement ce que la méthode est et n'est pas autorisé à le faire. De cette façon, les classes implémentant l'interface "ne sont pas autorisés" pour changer la mise en œuvre, bien qu'il n'y a pas de garanties.
N'importe qui pourrait écrire un
Collection
qui adhère à l'interface, puis fait des choses dans les méthodes qui sont absolument contre-intuitif, il n'y a aucun moyen de vous protéger de cela, d'autres que l'écriture de vastes tests unitaires.final
a été décidé de ne pas être admis sur Java 8interface
méthodes. L'insuffisance du rapport coût / bénéfice est un bon candidat, mais jusqu'à présent, c'est de la spéculation.