2009-10-03 19 views
86

Sto solo cercando di capire perché tutti i campi definiti in un'interfaccia sono implicitamente static e final. L'idea di mantenere i campi static ha senso per me dato che non puoi avere oggetti di un'interfaccia, ma perché sono final (implicitamente)?Perché tutti i campi di un'interfaccia sono implicitamente statici e definitivi?

Qualcuno sa perché i progettisti Java sono andati con rendere i campi in un'interfaccia static e final?

risposta

115

Un'interfaccia non può avere un comportamento o uno stato poiché si intende specificare solo un contratto di interazione, nessun dettaglio di implementazione. Nessun comportamento viene applicato non consentendo ai corpi del metodo/costruttore o ai blocchi di inizializzazione dell'istanza/dell'istanza. Nessuno stato viene applicato consentendo solo campi finali statici. Di conseguenza, la classe può avere uno stato (stato statico), ma lo stato dell'istanza non viene dedotto dall'interfaccia.

BTW: una costante in Java è definita da un campo finale statico (e per convenzione il nome utilizza UPPER_CASE_AND_UNDERSCORES).

+47

Non è necessariamente vero che i campi finali sono costanti; questo è garantito solo per i tipi primitivi. In generale, la parola chiave finale indica semplicemente che la posizione della memoria non cambierà. – Pops

+7

Non ho detto che i campi finali sono costanti, solo che le costanti sono campi finali. Si noti che è consentito inserire un campo finale statico non primitivo in un'interfaccia. Anche se il contenuto di quel campo potrebbe cambiare, il riferimento ad esso è costante. –

+1

@AdriaanKoster Hai detto esattamente che il campo finale è costante: * Nessuno stato è applicato solo consentendo costanti. * - questa frase implica che tutti i campi finali sono costanti. Potresti provare a discutere ulteriormente delle parole che hai usato, ma ovviamente la tua dichiarazione è in leasing fuorviante. –

9

I campi devono essere statici perché non possono essere astratti (come i metodi possono). Poiché non possono essere astratti, gli implementatori non saranno in grado di fornire logicamente la diversa implementazione dei campi.

I campi devono essere definitivi, credo, poiché i campi possono essere accessibili da molti diversi implementatori che consentono di essere modificabili potrebbero essere problematici (come la sincronizzazione). Anche per evitare che venga re-implementato (nascosto).

Solo il mio pensiero.

+0

NawMan, la tua spiegazione su "I campi devono essere statici ..." non ha molto senso. Ma tu eri molto nel giusto "I campi devono essere definitivi ..." – peakit

+1

Non penso che abbia ragione sul motivo per cui i campi devono essere definitivi. Consentire a diversi implementatori di modificare un campo non è problematico, poiché altrimenti l'ereditarietà sarebbe problematica. I campi devono essere definitivi, come ha detto Adriaan, perché un'interfaccia è, e dovrebbe, essere senza stato. In sostanza un'interfaccia con uno stato dovrebbe essere una classe astratta. –

+0

Se si dispone di un campo 'public static' che non è' final', findbugs si lamenterà (giustamente!). –

16

ci sono un paio di punti glossati qui:

Solo perché i campi in un'interfaccia sono implicitamente static final non significa che essi devono essere costanti di compilazione, o addirittura immutabile. Puoi definire ad es.

interface I { 
    String TOKEN = SomeOtherClass.heavyComputation(); 
    JButton BAD_IDEA = new JButton("hello"); 
} 

(Attenzione che questa operazione all'interno di una definizione annotazione può confuse javac, relativo al fatto che la suddetta effettivamente compila un inizializzatore statico.)

Inoltre, il motivo di questa limitazione è più stilistico che tecnico e molte persone vorrebbero lo like to see it be relaxed.

20

ragione d'essere final

eventuali implementazioni può cambiare il valore di campi se non sono definiti come finale. Quindi diventerebbero parte dell'attuazione. Un'interfaccia è una specifica pura senza alcuna implementazione.

ragione d'essere static

Se sono statici, allora essi appartengono all'interfaccia, e non l'oggetto, né il tipo di runtime dell'oggetto.

2

Ritengo che i campi siano definitivi indebitamente restrittivi e un errore da parte dei progettisti del linguaggio Java. Ci sono momenti, ad es. gestione degli alberi, quando è necessario impostare le costanti nell'implementazione necessarie per eseguire operazioni su un oggetto del tipo di interfaccia. La selezione di un percorso di codice nella classe di implementazione è un kludge.La soluzione che uso è quello di definire una funzione di interfaccia e implementarlo restituendo un letterale:

public interface iMine { 
    String __ImplementationConstant(); 
    ... 
} 

public class AClass implements iMine { 
    public String __ImplementationConstant(){ 
     return "AClass value for the Implementation Constant"; 
    } 
    ... 
} 

public class BClass implements iMine { 
    public String __ImplementationConstant(){ 
     return "BClass value for the Implementation Constant"; 
    } 
    ... 
} 

Tuttavia, sarebbe più semplice, più chiara e meno soggetto a attuazione aberrante per utilizzare questa sintassi:

public interface iMine { 
    String __ImplementationConstant; 
    ... 
} 

public class AClass implements iMine { 
    public static String __ImplementationConstant = 
     "AClass value for the Implementation Constant"; 
    ... 
} 

public class BClass implements iMine { 
    public static String __ImplementationConstant = 
     "BClass value for the Implementation Constant"; 
    ... 
} 
+0

Sembra che ti lamenti di più sui campi che sono statici che definitivi. –

0

Specifiche, contratti ... L'istruzione macchina per l'accesso al campo utilizza l'indirizzo dell'oggetto più l'offset del campo. Poiché le classi possono implementare molte interfacce, non c'è modo di rendere il campo dell'interfaccia non finale lo stesso offset in tutte le classi che estendono questa interfaccia. Pertanto, è necessario implementare diversi meccanismi per l'accesso al campo: due accessi alla memoria (ottenga l'offset del campo, ottiene il valore del campo) invece di uno più mantenendo il tipo di tabella dei campi virtuali (analogamente alla tabella dei metodi virtuali). Immagino che non volessero complicare jvm per funzionalità che possono essere facilmente simulate tramite materiali esistenti (metodi).

In scala possiamo avere campi nelle interfacce, sebbene internamente siano implementati come ho spiegato sopra (come metodi).

-1

static:

Tutto (variabile o metodo) che è static in Java può essere invocata Classname.variablename o Classname.methodname o direttamente. Non è obbligatorio invocarlo solo utilizzando il nome dell'oggetto.

Nell'interfaccia, gli oggetti non possono essere dichiarati e static consente di richiamare variabili solo attraverso il nome della classe senza la necessità del nome dell'oggetto.

final:

aiuta a mantenere un valore costante per una variabile in quanto non può essere ignorato nelle sue sottoclassi.

Problemi correlati