Perché dovrebbe essere utilizzata un’interfaccia nidificata statica in Java?

Ho appena trovato un’interfaccia annidata statica nella nostra base di codice.

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

Non l’ho mai visto prima. Lo sviluppatore originale è fuori dalla portata. Quindi devo chiedere COSI ‘:

Quali sono le semantiche dietro un’interfaccia statica? Cosa cambierebbe, se rimuovo la static ? Perché qualcuno dovrebbe farlo?

La parola chiave statica nell’esempio precedente è ridondante (un’interfaccia nidificata è automaticamente “statica”) e può essere rimossa senza alcun effetto sulla semantica; Lo consiglierei di essere rimosso. Lo stesso dicasi per “pubblico” sui metodi di interfaccia e “pubblico finale” sui campi di interfaccia: i modificatori sono ridondanti e aggiungono solo ingombro al codice sorgente.

Ad ogni modo, lo sviluppatore sta semplicemente dichiarando un’interfaccia chiamata Foo.Bar. Non esiste un’ulteriore associazione con la class allegata, tranne che il codice che non può accedere a Foo non sarà in grado di accedere a Foo.Bar. (Dal codice sorgente – bytecode o reflection possono accedere a Foo.Bar anche se Foo è pacchetto-privato!)

È accettabile che lo stile crei un’interfaccia nidificata in questo modo se ci si aspetta che venga utilizzata solo dalla class esterna, in modo da non creare un nuovo nome di livello superiore. Per esempio:

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

Alla domanda è stata data una risposta, ma una buona ragione per usare un’interfaccia annidata è se la sua funzione è direttamente correlata alla class in cui si trova. Un buon esempio di ciò è un Listener . Se avessi una class Foo e volessi che altre classi fossero in grado di ascoltare eventi su di essa, potresti dichiarare un’interfaccia chiamata FooListener , che è ok, ma sarebbe probabilmente più chiaro dichiarare un’interfaccia annidata e avere quelle altre classi implementare Foo.Listener (una class nidificata Foo.Event non è male insieme a questo).

Le interfacce dei membri sono implicitamente statiche. Il modificatore statico nell’esempio può essere rimosso senza modificare la semantica del codice. Vedi anche la specifica del linguaggio Java 8.5.1. Dichiarazioni del tipo di membro statico

Un’interfaccia interna deve essere statica per poter accedere. L’interfaccia non è associata alle istanze della class, ma alla class stessa, quindi sarebbe accessibile con Foo.Bar , in questo modo:

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

Nella maggior parte dei casi, questo non è diverso da una class interiore statica.

La risposta di Jesse è vicina, ma penso che ci sia un codice migliore per dimostrare perché un’interfaccia interna può essere utile. Guarda il codice qui sotto prima di continuare a leggere. Riesci a capire perché l’interfaccia interna è utile? La risposta è che la class DoSomething può già essere istanziata con qualsiasi class che implementa A e C; non solo lo zoo di class in cemento. Naturalmente, questo può essere ottenuto anche se AC non è interiore, ma immagina di concatenare nomi più lunghi (non solo A e C), e farlo per altre combinazioni (ad esempio, A e B, C e B, ecc.) E facilmente guarda come vanno le cose fuori controllo Per non parlare del fatto che le persone che esaminano il tuo albero dei sorgenti saranno sopraffatte da interfacce significative solo in una class. Quindi, per riassumere, un’interfaccia interna consente la costruzione di tipi personalizzati e migliora la loro incapsulamento .

 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; } } 

Per rispondere alla tua domanda molto direttamente, guarda su Map.Entry.

Map.Entry

anche questo può essere utile

Inserimento nel blog di Inerfaces con nidificazione statica

Se cambierete class Foo nell’interfaccia Foo, anche la parola chiave “pubblica” nell’esempio precedente sarà ridondante

l’interfaccia definita all’interno di un’altra interfaccia implicitamente è statica pubblica.

In genere vedo le classi interne statiche. Le classi interne statiche non possono fare riferimento alle classi contenenti che possono essere classi non statiche. A meno che tu non abbia a che fare con alcune collisioni di pacchetti (c’è già un’interfaccia chiamata Bar nello stesso pacchetto di Foo) penso che lo farei come un file proprio. Potrebbe anche essere una decisione progettuale per rafforzare la connessione logica tra Foo e Bar. Forse l’autore intendeva usare Bar solo con Foo (anche se un’interfaccia interna statica non imporrebbe questo, solo una connessione logica)

Nel 1998, Philip Wadler suggerì una differenza tra interfacce statiche e interfacce non statiche.

Per quanto posso vedere, l’unica differenza nel rendere un’interfaccia non statica è che ora può includere classi interne non statiche; quindi la modifica non renderebbe non valido alcun programma Java esistente.

Ad esempio, ha proposto una soluzione al problema dell’espressione , che è la mancata corrispondenza tra espressione come “quanto può esprimere la tua lingua” da un lato ed espressione come “i termini che stai cercando di rappresentare nella tua lingua” dall’altro .

Un esempio della differenza tra interfacce nidificate statiche e non statiche può essere visto nel suo codice di esempio :

 // This code does NOT compile class LangF> { interface Visitor { public R forNum(int n); } interface Exp { // since Exp is non-static, it can refer to the type bound to This public  R visit(This.Visitor v); } } 

Il suo suggerimento non lo ha mai fatto in Java 1.5.0. Quindi, tutte le altre risposte sono corrette: non vi è alcuna differenza tra interfacce nidificate statiche e non statiche.

In Java, l’interfaccia / class statica consente di utilizzare l’interfaccia / class come una class di livello superiore, ovvero può essere dichiarata da altre classi. Quindi, puoi fare:

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

Senza la statica, il precedente non riuscirebbe a compilare. Il vantaggio di questo è che non è necessario un nuovo file sorgente solo per dichiarare l’interfaccia. Inoltre associa visivamente l’interfaccia Bar alla class Foo poiché è necessario scrivere Foo.Bar e implica che la class Foo faccia qualcosa con istanze di Foo.Bar.

Una descrizione dei tipi di class in Java .

Statico significa che qualsiasi parte di class del pacchetto (progetto) può accedervi senza utilizzare un puntatore. Questo può essere utile o difficile a seconda della situazione.

L’esempio perfetto dell’utilità dei metodi “statici” è la class Math. Tutti i metodi in Math sono statici. Ciò significa che non devi fare di tutto, creare una nuova istanza, dichiarare variabili e memorizzarle in più variabili, puoi semplicemente inserire i tuoi dati e ottenere un risultato.

Statico non è sempre così utile. Ad esempio, se stai facendo un confronto tra maiuscole e minuscole, potresti voler memorizzare i dati in diversi modi. Non è ansible creare tre metodi statici con firme identiche. Hai bisogno di 3 istanze diverse, non statiche, e quindi puoi e confrontale, causale se è statica, i dati non cambieranno insieme all’input.

I metodi statici sono buoni per i ritorni una tantum e calcoli rapidi o dati ottenuti facilmente.