Question

Je viens de trouver une interface imbriquée statique dans notre base de code.

class Foo {
    public static interface Bar {
        /* snip */
    }
    /* snip */
}

Je n'ai jamais vu cela auparavant. Le développeur d'origine est hors de portée. Je dois donc demander à SO:

Quelle est la sémantique derrière une interface statique? Qu'est-ce qui changerait si je supprimais le static ? Pourquoi quelqu'un ferait-il cela?

Était-ce utile?

La solution

Le mot clé static dans l'exemple ci-dessus est redondant (une interface imbriquée est automatiquement "statique") et peut être supprimé sans effet sur la sémantique. Je recommanderais qu'il soit supprimé. Il en va de même pour " public " sur les méthodes d'interface et "public final". sur les champs d'interface - les modificateurs sont redondants et ne font qu'ajouter du fouillis au code source.

Quoi qu'il en soit, le développeur déclare simplement une interface nommée Foo.Bar. Il n'y a pas d'autre association avec la classe englobante, sauf que le code qui ne peut pas accéder à Foo ne pourra pas non plus accéder à Foo.Bar. (À partir du code source - le bytecode ou la réflexion peut accéder à Foo.Bar même si Foo est paquet-privé!)

Il est acceptable de créer une interface imbriquée de cette façon si vous vous attendez à ce qu'elle soit utilisée uniquement à partir de la classe externe, afin de ne pas créer de nouveau nom de niveau supérieur. Par exemple:

public class Foo {
    public interface Bar {
        void callback();
    }
    public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
    public void callback() {...}
});

Autres conseils

La question a été résolue, mais une bonne raison d'utiliser une interface imbriquée est si sa fonction est directement liée à la classe dans laquelle elle se trouve. Un bon exemple de ceci est un Listener . Si vous aviez une classe Foo et que vous vouliez que les autres classes puissent écouter les événements, vous pouvez déclarer une interface nommée FooListener , ce qui est correct, mais ce serait correct. Il serait probablement plus clair de déclarer une interface imbriquée et de faire en sorte que ces autres classes implémentent Foo.Listener (une classe imbriquée Foo.Event n'est pas mauvaise avec cela).

Les interfaces membres sont implicitement statiques. Le modificateur statique de votre exemple peut être supprimé sans modifier la sémantique du code. Voir aussi la spécification du langage Java 8.5.1. Déclarations statiques de type de membre

Une interface interne doit être statique pour être accessible. L’interface n’est pas associée aux instances de la classe, mais à la classe elle-même; elle serait donc accessible via Foo.Bar , comme suit:

public class Baz implements Foo.Bar {
   ...
}

Dans la plupart des cas, ce n'est pas différent d'une classe interne statique.

La réponse de Jesse est proche, mais je pense qu'il existe un meilleur code pour démontrer pourquoi une interface interne peut être utile. Regardez le code ci-dessous avant de continuer à lire. Pouvez-vous trouver pourquoi l'interface interne est utile? La réponse est que la classe DoSomethingAlready peut être instanciée avec n’importe quelle classe qui implémente A et C; pas seulement le zoo concret de classe. Bien sûr, cela peut être réalisé même si AC n’est pas interne, mais imaginez concaténer des noms plus longs (pas seulement A et C), et pour d’autres combinaisons (par exemple, A et B, C et B, etc.) et vous facilement. voyez comment les choses deviennent incontrôlables. Sans oublier que les personnes qui consultent votre arborescence source seront submergées par des interfaces significatives dans une seule classe. Pour résumer, une interface interne permet de construire des types personnalisés et améliore leur encapsulation .

class ConcreteA implements A {
 :
}

class ConcreteB implements B {
 :
}

class ConcreteC implements C {
 :
}

class Zoo implements A, C {
 :
}

class DoSomethingAlready {
  interface AC extends A, C { }

  private final AC ac;

  DoSomethingAlready(AC ac) {
    this.ac = ac;
  }
}

Pour répondre à votre question très directement, consultez Map.Entry.

Map.Entry

aussi cela peut être utile

entrée de blog Inerfaces statiques

En général, je vois des classes internes statiques. Les classes internes statiques ne peuvent pas référencer les classes contenant ce que les classes non statiques peuvent faire. À moins que vous ne rencontriez des problèmes de collision de paquet (il y a déjà une interface appelée Bar dans le même paquet que Foo), je pense que j'en ferais un fichier propre. Il pourrait également être une décision de conception d'imposer la connexion logique entre Foo et Bar. L’auteur voulait peut-être utiliser Bar uniquement avec Foo (bien qu’une interface interne statique ne l’impose pas, mais simplement une connexion logique)

Si vous voulez changer la classe Foo en interface Foo, le "public" mot-clé dans l'exemple ci-dessus sera également redondant, car

  Une interface

définie dans une autre interface sera implicitement publique   statique.

En 1998, Philip Wadler a suggéré une différence entre les interfaces statiques et les interfaces non statiques.

  

Autant que je sache, la seule différence pour faire un   interface non statique est qu'il peut maintenant inclure interne non statique   Des classes; de sorte que le changement ne rendrait pas invalide tout Java existant   programmes.

Par exemple, il a proposé une solution au problème d'expression , qui correspond au décalage entre les expressions. en tant que "combien votre langue peut-elle exprimer"? d'une part et l'expression comme "les termes que vous essayez de représenter dans votre langue" d'autre part.

Vous trouverez un exemple de différence entre les interfaces imbriquées statiques et non statiques dans son exemple de code :

// This code does NOT compile
class LangF<This extends LangF<This>> {
    interface Visitor<R> {
        public R forNum(int n);
    }

    interface Exp {
        // since Exp is non-static, it can refer to the type bound to This
        public <R> R visit(This.Visitor<R> v);
    }
}

Sa suggestion ne l’a jamais été en Java 1.5.0. Par conséquent, toutes les autres réponses sont correctes: il n'y a pas de différence entre les interfaces imbriquées statiques et non statiques.

En Java, l’interface / classe statique permet de l’utiliser comme une classe de niveau supérieur, c’est-à-dire qu’elle peut être déclarée par d’autres classes. Donc, vous pouvez faire:

class Bob
{
  void FuncA ()
  {
    Foo.Bar foobar;
  }
}

Sans la statique, la compilation ci-dessus échouerait. L'avantage est que vous n'avez pas besoin d'un nouveau fichier source pour déclarer l'interface. Il associe également visuellement l’interface Bar à la classe Foo puisque vous devez écrire Foo.Bar et implique que la classe Foo fait quelque chose avec les instances de Foo.Bar.

Une description des types de classe en Java .

Statique signifie que toute partie de classe du package (projet) peut y accéder sans utiliser de pointeur. Cela peut être utile ou gênant selon la situation.

L’exemple parfait de l’utilité de "statique" méthodes est la classe de mathématiques. Toutes les méthodes en maths sont statiques. Cela signifie que vous ne devez pas vous gêner, créer une nouvelle instance, déclarer des variables et les stocker dans encore plus de variables, vous pouvez simplement entrer vos données et obtenir un résultat.

La statique n'est pas toujours utile. Si vous comparez des cas, par exemple, vous souhaiterez peut-être stocker des données de différentes manières. Vous ne pouvez pas créer trois méthodes statiques avec des signatures identiques. Vous avez besoin de 3 instances différentes, non statiques, et ensuite vous pouvez et comparer, car si c'est statique, les données ne changeront pas avec l'entrée.

Les méthodes statiques sont bonnes pour les retours uniques, les calculs rapides ou les données faciles à obtenir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top