Java 8 autorise les méthodes d'interface statiques
Avec Java 8, les interfaces puede ont des méthodes statiques. Ils peuvent également avoir des méthodes d'instance concrètes, mais pas de champs d'instance.
Il y a vraiment deux questions ici :
- Pourquoi, au bon vieux temps, les interfaces ne pouvaient-elles pas contenir de méthodes statiques ?
- Pourquoi les méthodes statiques ne peuvent-elles pas être surchargées ?
Méthodes statiques dans les interfaces
Aucune raison technique solide n'empêchait les interfaces d'avoir des méthodes statiques dans les versions précédentes. Ceci est résumée joliment par l'affiche d'une question dupliquée. Les méthodes d'interface statiques étaient initialement considérées comme un petit changement de langue, et puis il y a eu une proposition officielle pour les ajouter dans Java 7, mais il a été plus tard abandonné en raison de complications imprévues.
Enfin, Java 8 a introduit des méthodes d'interface statiques, ainsi que des méthodes d'instance modifiables avec une implémentation par défaut. Cependant, elles ne peuvent toujours pas avoir de champs d'instance. Ces fonctionnalités font partie de la prise en charge des expressions lambda, et vous pouvez en savoir plus à leur sujet dans Partie H de JSR 335.
Remplacement des méthodes statiques
La réponse à la deuxième question est un peu plus compliquée.
Les méthodes statiques sont résolubles au moment de la compilation. La répartition dynamique est logique pour les méthodes d'instance, lorsque le compilateur ne peut pas déterminer le type concret de l'objet et, par conséquent, ne peut pas résoudre la méthode à invoquer. Mais l'invocation d'une méthode statique nécessite une classe, et puisque cette classe est connue, le compilateur ne peut pas la résoudre. statiquement -au moment de la compilation, la répartition dynamique est inutile.
Il est nécessaire de connaître un peu le fonctionnement des méthodes d'instance pour comprendre ce qui se passe ici. Je suis sûr que la mise en œuvre réelle est très différente, mais laissez-moi vous expliquer ma notion de la répartition des méthodes, qui modélise fidèlement le comportement observé.
Imaginez que chaque classe possède une table de hachage qui associe les signatures de méthodes (nom et types de paramètres) à un morceau de code réel pour implémenter la méthode. Lorsque la machine virtuelle tente d'invoquer une méthode sur une instance, elle interroge l'objet pour connaître sa classe et recherche la signature demandée dans la table de la classe. Si un corps de méthode est trouvé, il est invoqué. Sinon, la classe parente de la classe est obtenue et la recherche y est répétée. L'opération se poursuit jusqu'à ce que la méthode soit trouvée ou qu'il n'y ait plus de classes parentes - ce qui entraîne un message d'erreur NoSuchMethodError
.
Si une superclasse et une sous-classe ont toutes deux une entrée dans leurs tables pour la même signature de méthode, la version de la sous-classe est rencontrée en premier, et la version de la superclasse n'est jamais utilisée - il s'agit d'une "surcharge".
Maintenant, supposons que l'on saute l'instance de l'objet et que l'on commence simplement par une sous-classe. La résolution pourrait se faire comme ci-dessus, ce qui vous donnerait une sorte de méthode statique "surchargeable". Cependant, la résolution peut se faire au moment de la compilation, puisque le compilateur part d'une classe connue, plutôt que d'attendre l'exécution pour demander à un objet d'un type non spécifié sa classe. Il n'y a aucun intérêt à "surcharger" une méthode statique puisqu'on peut toujours spécifier la classe qui contient la version désirée.
Constructeur "interfaces
Voici un peu plus de matériel pour répondre à la récente modification de la question.
Il semble que vous souhaitiez imposer une méthode de type constructeur pour chaque mise en œuvre de l'option IXMLizable
. Oubliez un instant l'idée d'essayer de faire respecter cette exigence par une interface, et imaginez que vous avez des classes qui répondent à cette exigence. Comment l'utiliseriez-vous ?
class Foo implements IXMLizable<Foo> {
public static Foo newInstanceFromXML(Element e) { ... }
}
Foo obj = Foo.newInstanceFromXML(e);
Puisque vous devez nommer explicitement le type concret Foo
lors de la "construction" du nouvel objet, le compilateur peut vérifier qu'il possède bien la méthode de fabrique nécessaire. Et si ce n'est pas le cas, alors quoi ? Si je peux implémenter un IXMLizable
qui n'a pas de "constructeur", et que je crée une instance et que je la passe à votre code, elle es un IXMLizable
avec toute l'interface nécessaire.
La construction fait partie de la mise en œuvre, pas l'interface. Tout code qui fonctionne avec succès avec l'interface ne se soucie pas du constructeur. Tout code qui se soucie du constructeur a besoin de connaître le type concret de toute façon, et l'interface peut être ignorée.
4 votes
Il n'est pas nécessaire d'encombrer les définitions de méthodes (et de champs) de public dans les interfaces, d'ailleurs.
0 votes
Hmm, il semble qu'il s'agisse d'un doublon de stackoverflow.com/questions/21817/ . Je n'avais pas vu ça avant.
1 votes
Pourriez-vous fournir un code permettant d'utiliser les méthodes de l'interface statique ?
0 votes
Également dupe de stackoverflow.com/questions/129267/
0 votes
@Erickson,Pourriez-vous illustrer avec un exemple où l'utilisation d'une méthode statique échoue dans l'interface
44 votes
Cela sera possible dans Java 8 : docs.oracle.com/javase/tutorial/java/IandI/
1 votes
@dakshang Oui, mais cela ne fait pas ce que le PO veut.
0 votes
Duplicata possible de Pourquoi pas de méthodes statiques dans les interfaces, mais des champs statiques et des classes internes ? [pré-Java8]
0 votes
La question de @JohnMercier est maintenant close. C'est maintenant le vrai fil de discussion
0 votes
Cela est possible en Java 8 - consultez ma réponse ci-dessous : stackoverflow.com/a/31162902/1216775