92 votes

Pourquoi aucune méthode statique dans les interfaces, mais des champs statiques et des classes internes OK? [avant Java8]

Il y a eu quelques questions posées ici sur pourquoi vous ne pouvez pas définir de méthodes statiques dans les interfaces, mais aucune d'entre elles n'aborde une incohérence fondamentale : pourquoi peut-on définir des champs statiques et des types internes statiques dans une interface, mais pas des méthodes statiques ?

Les types internes statiques ne sont peut-être pas une comparaison équitable, car il s'agit simplement de sucre syntaxique qui génère une nouvelle classe, mais pourquoi des champs mais pas des méthodes ?

Un argument contre les méthodes statiques dans les interfaces est que cela casse la stratégie de résolution de la table virtuelle utilisée par la JVM, mais cela ne devrait-il pas s'appliquer de manière égale aux champs statiques, c'est-à-dire que le compilateur peut simplement l'incorporer ?

La cohérence est ce que je recherche, et Java aurait dû soit ne pas supporter de statiques sous aucune forme dans une interface, soit être cohérent et les autoriser.

0 votes

Les champs sont définis alors que la méthode n'a pas de corps. Tenter d'appeler la méthode provoquera une erreur, tandis que les variables seront toujours présentes : qu'elles soient par défaut ou définies.

1 votes

bugs.sun.com/view_bug.do?bug_id=4093687 - fermé ne sera pas fixé avec plus de 200 votes, et c'était en 1997...

0 votes

@erickson - pourquoi dis-tu que c'est une réponse échouant à une interview ?

48voto

erickson Points 127945

Une proposition officielle a été faite pour permettre les méthodes statiques dans les interfaces en Java 7. Cette proposition est faite dans le cadre du Projet Coin.

Mon avis personnel est que c'est une excellente idée. Il n'y a aucune difficulté technique pour l'implémentation, et c'est une chose très logique et raisonnable à faire. Il y a plusieurs propositions dans le Projet Coin que j'espère ne feront jamais partie du langage Java, mais celle-ci pourrait nettoyer beaucoup d'API. Par exemple, la classe Collections pour manipuler toute implémentation de List; celles-ci pourraient être incluses dans l'interface List.

[

](http://java.sun.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List))

Mise à jour: Dans le podcast Java Posse #234, Joe D'arcy a mentionné brièvement la proposition, en disant qu'elle était "complexe" et qu'elle ne ferait probablement pas partie du Projet Coin.


Mise à jour: Bien qu'elles ne soient pas incluses dans le Projet Coin pour Java 7, Java 8 prend en charge les fonctions statiques dans les interfaces.

5 votes

Il semble que les méthodes statiques dans les interfaces arrivent dans Java 8.

2 votes

Le nouveau Java 8 java.util.function.Function a déclaré une méthode statique identity. donc oui, en Java 8, nous avons des méthodes statiques dans les interfaces.

40voto

skaffman Points 197885

Je vais opter pour ma théorie personnelle pour celle-ci, qui est que le manque de cohérence dans ce cas est une question de commodité plutôt que de conception ou de nécessité, puisque je n'ai entendu aucun argument convaincant soutenant que c'était l'un ou l'autre.

Les champs statiques sont là (a) parce qu'ils étaient là dans JDK 1.0, et de nombreuses décisions douteuses ont été prises dans JDK 1.0, et (b) les champs statiques finaux dans les interfaces sont la chose la plus proche que java avait aux constantes à l'époque.

Les classes internes statiques dans les interfaces étaient autorisées parce que c'est du sucre syntaxique pur - la classe interne n'a en réalité rien à voir avec la classe parente.

Donc, les méthodes statiques ne sont pas autorisées simplement parce qu'il n'y a aucune raison convaincante de le faire ; la cohérence n'est pas suffisamment convaincante pour changer le statu quo.

Bien sûr, cela pourrait être permis dans les futures versions du JLS sans rien casser.

1 votes

Je dois admettre que je ne comprends toujours pas pourquoi vous trouvez surprenant que les méthodes statiques ne soient pas autorisées dans les interfaces. Ce serait une bonne idée si vous expliquiez pourquoi elles devraient être autorisées en premier lieu. Pas d'offense, je suis simplement curieux, je ne vois pas pourquoi les méthodes statiques devraient faire partie des interfaces...

3 votes

Simplement pour des raisons de cohérence, pas pour des raisons de conception. Si vous prévoyez d'autoriser des statiques de quelque nature que ce soit dans les interfaces, alors vous devriez autoriser tous les statiques, pas seulement certains types.

1 votes

Oublions la syntaxe pendant une seconde. Je pense que Sun a décidé qu'ils avaient besoin d'une façon de définir des constantes (par exemple, des enums, des flags) dans les interfaces et la chose la plus proche qui existait en Java à l'époque était les champs static final. Comme discuté, ce n'est pas parfait (pas vraiment des constantes, pas de symétrie), mais...

15voto

DJClayworth Points 11288

Il n'y a jamais de raison de déclarer une méthode statique dans une interface. Elles ne peuvent pas être exécutées par l'appel normal MyInterface.staticMethod(). (EDIT: Comme cette dernière phrase a confondu certaines personnes, appeler MyClass.staticMethod() exécute précisément l'implémentation de staticMethod sur MyClass, ce qui, si MyClass est une interface, ne peut pas exister!) Si vous les appelez en spécifiant la classe implémentante MyImplementor.staticMethod(), alors vous devez connaître la classe réelle, donc il est sans importance que l'interface la contienne ou non.

Plus important encore, les méthodes statiques ne sont jamais remplacées, et si vous essayez de faire :

MyInterface var = new MyImplementingClass();
var.staticMethod();

les règles pour les statiques disent que la méthode définie dans le type déclaré de var doit être exécutée. Comme c'est une interface, c'est impossible.

Vous pouvez bien sûr toujours supprimer le mot-clé statique de la méthode. Tout fonctionnera bien. Vous devrez peut-être supprimer certains avertissements s'il est appelé à partir d'une méthode d'instance.

Pour répondre à certains des commentaires ci-dessous, la raison pour laquelle vous ne pouvez pas exécuter "result=MyInterface.staticMethod()" est que cela devrait exécuter la version de la méthode définie dans MyInterface. Mais il ne peut pas y avoir de version définie dans MyInterface, car c'est une interface. Elle n'a pas de code par définition.

2 votes

"Ils ne peuvent pas être exécutés par l'appel normal MyInterface.staticMethod()." Pourquoi pas ? Je pensais que c'était le but de la question - pourquoi n'est-ce pas autorisé ?"

16 votes

Je suis d'accord, n'est-ce pas le point de la question ? Cette réponse est une tautologie - "Vous ne pouvez pas le faire car ça ne marche pas !"

0 votes

D'accord, bonne réponse, mais pour une autre question ;-)

6voto

Alexander Points 4298

Le but des interfaces est de définir un contrat sans fournir une implémentation. Par conséquent, vous ne pouvez pas avoir de méthodes statiques, car elles devraient avoir une implémentation déjà dans l'interface puisque vous ne pouvez pas remplacer les méthodes statiques. En ce qui concerne les champs, seuls les champs finaux statiques sont autorisés, qui sont, essentiellement, des constantes (en 1.5+, vous pouvez également avoir des énumérations dans les interfaces). Les constantes sont là pour aider à définir l'interface sans nombres magiques.

En passant, il n'est pas nécessaire de spécifier explicitement les modificateurs static final pour les champs dans les interfaces, car seuls les champs statiques finaux sont autorisés.

4 votes

Tout d'abord, les finales statiques ne sont pas des constantes, c'est une réponse qui fait échouer l'entretien. Deuxièmement, aucune de ces réponses n'explique pourquoi vous pouvez avoir des champs statiques et des classes internes dans une interface, mais pas de méthodes.

0 votes

Bien sûr, vous pouvez modifier les valeurs des champs finaux statiques si vous utilisez des types complexes, mais vous ne pouvez toujours pas les réaffecter. Bien sûr, vous pouvez contourner l'idée selon laquelle ils sont destinés à être utilisés comme un remplacement pour les nombres magiques, mais c'est uniquement en raison de la syntaxe de Java.

0 votes

Veuillez relire ma réponse si vous pensez que je n'ai pas répondu à pourquoi les méthodes statiques ne sont pas autorisées.

6voto

Ceci est un vieux fil de discussion, mais c'est une question très importante pour tous. Comme je viens de le remarquer aujourd'hui, j'essaie de l'expliquer de manière plus claire :

Le but principal de l'interface est de fournir quelque chose qui est impossible à implémenter, donc s'ils fournissent

des méthodes statiques autorisées

alors vous pouvez appeler cette méthode en utilisant nomInterface.nomMéthodeStatique(), mais il s'agit d'une méthode non implémentée et ne contient rien. Il est donc inutile d'autoriser les méthodes statiques. C'est pourquoi ils ne le font pas du tout.

les champs statiques sont autorisés

parce que les champs ne sont pas implémentables, par implémentables je veux dire que vous ne pouvez pas effectuer d'opération logique dans un champ, vous pouvez effectuer des opérations sur un champ. Vous ne changez donc pas le comportement du champ, c'est pourquoi ils sont autorisés.

Les classes internes sont autorisées

Les classes internes sont autorisées parce qu'après la compilation, un fichier de classe différent de la classe interne est créé, disons NomInterface$NomClasseInterne.class, donc fondamentalement vous fournissez une implémentation dans une entité différente mais pas dans l'interface. L'implémentation dans les classes internes est donc fournie.

J'espère que cela vous aidera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X