Perché le variabili di interfaccia sono statiche e definitive per impostazione predefinita?


274

Perché le variabili di interfaccia sono statiche e finali per impostazione predefinita in Java?


41
Non inserire variabili all'interno delle interfacce.
Cherouvim,

34
Perché le interfacce definiscono contratti che possono essere implementati in vari modi. Il valore di una variabile è l'implementazione.
Cherouvim,

10
Possiamo certamente quando sappiamo che tutte le classi che implementano l'interfaccia hanno alcune variabili costanti (nomi dei campi per esempio).
Aniket Thakur il

È una buona idea trasformare una variabile in una classe in un'istanza dell'interfaccia implementata dalla classe? L'ho già sentito prima.
Doug Hauf,

Le interfacce in Java seguono il principio ACID, finale a causa della normalizzazione in C. @cherouvim Il tipo di una variabile è l'implementazione, una variabile deve essere dichiarata, con o senza un valore e la definizione di una variabile è il valore. Se si modifica il valore di una variabile non è reimplementazione, la sua ridefinizione.
Grim

Risposte:


264

Dalle FAQ sulla progettazione dell'interfaccia Java di Philip Shaw:

Le variabili di interfaccia sono statiche perché non è possibile creare un'istanza delle interfacce Java; il valore della variabile deve essere assegnato in un contesto statico in cui non esiste alcuna istanza. Il modificatore finale assicura che il valore assegnato alla variabile di interfaccia sia una costante costante che non può essere riassegnata dal codice del programma.

fonte


39
Si noti che nessuna delle classi astratte non può essere istanziata "di per sé" né quelle che possono avere variabili di istanza.
macias,

18
Questa spiegazione per il staticmodificatore è completamente falsa. Le variabili di istanza pubblica di una classe fanno parte della sua interfaccia e non c'è motivo per cui non debbano essere astratte in un Java interface, proprio come i metodi di istanza. Non importa che un Java interfacenon possa essere istanziato direttamente: puoi comunque avere istanze di classi che implementano il interfaceed è sensato richiedere che abbiano una certa variabile di istanza pubblica. Per quanto riguarda la parte relativa final, ciò non offre affatto una spiegazione, ma descrive semplicemente cosa finalsignifica.
piroplastica,

3
La citazione sopra è migliore nel contesto. Il motivo è che "le variabili di interfaccia sono intese come costanti Java". La citazione stava solo elaborando il motivo per cui una tale costante sarebbe statica e definitiva. Questo è vero, ma la vera domanda è: perché le variabili non sono ammesse come parte dell'interfaccia effettiva (cioè specificare i nomi e i tipi di membri non privati ​​che devono presentarsi in una classe di implementazione). Se avessero voluto speciali "costanti di interfaccia", avrebbero potuto usare una nuova sintassi o semplicemente deciso che qualsiasi variabile effettivamente definita in un'interfaccia fosse costante di interfaccia.
piroplastica,

6
Le interfacce non possono avere variabili di istanza per evitare l'ereditarietà multipla di problemi di stato. Vedi docs.oracle.com/javase/tutorial/java/IandI/… . Una classe non può estendere più di una classe per lo stesso motivo.
denis,

1
Come vengono introdotti i metodi predefiniti e hanno istanza, ma la variabile di istanza non è supportata ...
M.kazem Akhgary

41

Dal momento che l'interfaccia non ha un oggetto diretto, l'unico modo per accedervi è usare una classe / interfaccia e quindi è per questo che se esiste una variabile di interfaccia, dovrebbe essere statica altrimenti non sarà affatto accessibile al mondo esterno. Ora poiché è statico, può contenere solo un valore e qualsiasi classe che lo implementa può cambiarlo e quindi sarà tutto un casino.

Quindi se esiste una variabile di interfaccia, sarà implicitamente statica, definitiva e ovviamente pubblica !!!


Naturalmente una variabile di istanza sarebbe accessibile se fosse consentita in un Java interface. Una classe implementerebbe l'interfaccia, dichiarando la variabile di istanza (come richiesto dall'interfaccia). Il suo costruttore (o altro metodo) imposta la variabile di istanza. Quando un'istanza della classe viene istanziata, sarai in grado di accedere alla sua variabile di istanza.
piroplastica,

Java consente l'esistenza di metodi statici con corpi in un'interfaccia. Quelli potrebbero accedere alle variabili statiche. Semplicemente non possono cambiarli, il che significa che le funzioni statiche non possono memorizzare alcun dato
simpleuser

36

pubblico : per l'accessibilità in tutte le classi, proprio come i metodi presenti nell'interfaccia

statico : poiché l'interfaccia non può avere un oggetto, interfaceName.variableName può essere utilizzato per fare riferimento a esso o direttamente variabileName nella classe che lo implementa.

finale : per renderli costanti. Se 2 classi implementano la stessa interfaccia e si dà a entrambe il diritto di modificare il valore, si verificherà un conflitto nel valore corrente di var, motivo per cui è consentita una sola inizializzazione.

Inoltre, tutti questi modificatori sono impliciti per un'interfaccia, non è necessario specificarli.


15

( Questa non è una risposta filosofica ma più di una pratica ). Il requisito per il staticmodificatore è ovvio a cui gli altri hanno risposto. Fondamentalmente, poiché le interfacce non possono essere istanziate, l'unico modo per accedere ai suoi campi è renderle un campo di classe - static.

Il motivo dietro cui i interfacecampi diventano automaticamente final(costanti) è impedire che diverse implementazioni cambino accidentalmente il valore della variabile di interfaccia, il che può influenzare inavvertitamente il comportamento delle altre implementazioni. Immagina lo scenario seguente in cui una interfaceproprietà non è diventata esplicitamente finalda Java:

public interface Actionable {
    public static boolean isActionable = false;

    public void performAction();
}

public NuclearAction implements Actionable {

    public void performAction() {
        // Code that depends on isActionable variable
        if (isActionable) {
            // Launch nuclear weapon!!!
        }
    }
}

Ora, pensa solo a cosa accadrebbe se un'altra classe che implementa Actionablealtera lo stato della variabile di interfaccia:

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

Se queste classi sono caricate all'interno di una singola JVM da un classloader, allora il comportamento di NuclearActionpuò essere influenzato da un'altra classe CleanAction, quando performAction()viene invocata dopo CleanActionl'esecuzione di (nello stesso thread o in altro modo), che in questo caso può essere disastroso (semanticamente quello è).

Poiché non sappiamo come ciascuna implementazione di un interfaceutilizzerà queste variabili, devono implicitamente esserlo final.


9

Perché qualsiasi altra cosa fa parte dell'implementazione e le interfacce non possono contenere alcuna implementazione.


1
allora qual è il motivo del finale.
Jothi,

7
Per indicare che è una costante. Java non ha una parola chiave const. finale statico è il modo in cui dichiari le costanti.
Amir Afghani,

5
A partire da Java 8, possono contenere un'implementazione, ma si consiglia vivamente di non utilizzarla se non è necessaria la compatibilità con i backwarts. :)
codepleb,

6
public interface A{
    int x=65;
}
public interface B{
    int x=66;
}
public class D implements A,B {
    public static void main(String[] a){
        System.out.println(x); // which x?
    }
}

Ecco la soluzione

System.out.println(A.x); // done

Penso che sia l'unico motivo per cui le variabili di interfaccia sono statiche.

Non dichiarare variabili all'interno di Interface.


3
In effetti, senza la specifica "Ax" non sarebbe nemmeno compilabile ", quindi in realtà è sicuro usare variabili (che implicitamente sono finali statici pubblici) nelle interfacce.
Marco,

Non sono d'accordo con la risposta, poiché @Marco ha detto che non si sarebbe nemmeno compilato. Finora non ho riscontrato alcun altro svantaggio, forse solo che non vedi scritto static finalprima della variabile che in realtà è statica e finale.
Micer,

5

statico - perché l'interfaccia non può avere alcuna istanza. e finale - perché non abbiamo bisogno di cambiarlo.


15
"non abbiamo bisogno" == "non ci è permesso", non mescolare i significati.
Peter - Ripristina Monica

3

perché:

Static : poiché non possiamo avere oggetti di interfacce, quindi dovremmo evitare di usare le variabili membro a livello di oggetto e dovremmo usare variabili a livello di classe, cioè statiche.

Final : in modo che non dovremmo avere valori ambigui per le variabili (problema Diamond - Ereditarietà multipla).

E secondo l'interfaccia della documentazione è un contratto e non un'implementazione.

riferimento: la risposta di Abhishek Jain su quora


2

Java non consente le variabili astratte e / o le definizioni dei costruttori nelle interfacce. Soluzione: appendere semplicemente una classe astratta tra l'interfaccia e l'implementazione che estende solo la classe astratta in questo modo:

 public interface IMyClass {

     void methodA();
     String methodB();
     Integer methodC();

 }

 public abstract class myAbstractClass implements IMyClass {
     protected String varA, varB;

     //Constructor
     myAbstractClass(String varA, String varB) {
         this.varA = varA;
         this.varB = VarB;
     }

     //Implement (some) interface methods here or leave them for the concrete class
     protected void methodA() {
         //Do something
     }

     //Add additional methods here which must be implemented in the concrete class
     protected abstract Long methodD();

     //Write some completely new methods which can be used by all subclasses
     protected Float methodE() {
         return 42.0;
     }

 }

 public class myConcreteClass extends myAbstractClass {

     //Constructor must now be implemented!
     myClass(String varA, String varB) {
         super(varA, varB);
     }

     //All non-private variables from the abstract class are available here
     //All methods not implemented in the abstract class must be implemented here

 }

Puoi anche usare una classe astratta senza alcuna interfaccia se sei SICURO di non voler implementarla insieme ad altre interfacce in un secondo momento. Si noti che non è possibile creare un'istanza di una classe astratta che DEVE prima estenderla.

(La parola chiave "protetta" significa che solo le classi estese possono accedere a questi metodi e variabili.)

Spyro



1

Interfaccia: servizio di requisiti di sistema.

Nell'interfaccia, le variabili sono assegnate per impostazione predefinita da un modificatore di accesso finale pubblico, statico . Perché :

pubblico: a volte succede che l'interfaccia possa essere inserita in qualche altro pacchetto. Quindi deve accedere alla variabile da qualsiasi parte del progetto.

statico: in quanto tale classe incompleta non può creare oggetto. Quindi nel progetto dobbiamo accedere alla variabile senza oggetto in modo da poter accedere con l'aiuto diinterface_filename.variable_name

final: supponiamo che un'interfaccia sia implementata da molte classi e che tutte le classi provino ad accedere e ad aggiornare la variabile di interfaccia. Quindi porta ad un'incoerenza nella modifica dei dati e influisce su ogni altra classe. Quindi è necessario dichiarare il modificatore di accesso con final.


0

In Java, l'interfaccia non consente di dichiarare alcuna variabile di istanza. L'uso di una variabile dichiarata in un'interfaccia come variabile di istanza restituirà un errore di tempo di compilazione.

È possibile dichiarare una variabile costante, usando static finalquale è diverso da una variabile di istanza.


Questo è chiaramente sbagliato. Il compilatore non si lamenterà se non lo rendi privato o protetto. Sotto il cofano, come altri hanno già detto, vengono convertiti in finale statico pubblico. E immagino sia abbastanza ovvio il perché. Perché l'interfaccia ha lo scopo di dettare il comportamento, non lo stato.
Mikayil Abdullayev,

0

L'interfaccia può essere implementata da qualsiasi classe e cosa succede se quel valore è stato modificato da una di queste classi di implementazione allora ci saranno fuorvianti per altre classi di implementazione. L'interfaccia è fondamentalmente un riferimento per combinare due entità correlate ma diverse. Pertanto, la variabile dichiarante all'interno dell'interfaccia sarà implicitamente finale e anche statica perché l'interfaccia non può essere istanziata.


0

Pensa a un'applicazione web in cui hai l'interfaccia definita e altre classi la implementano. Poiché non è possibile creare un'istanza di interfaccia per accedere alle variabili, è necessario disporre di una parola chiave statica. Poiché è statico, qualsiasi cambiamento nel valore si rifletterà su altre istanze che lo hanno implementato. Quindi per evitarlo li definiamo come finali.


0

Appena provato in Eclipse, la variabile nell'interfaccia è predefinita per essere finale, quindi non puoi cambiarla. Rispetto alla classe genitore, le variabili sono decisamente modificabili. Perché? Dal mio punto di vista, la variabile in classe è un attributo che verrà ereditato dai bambini, che possono cambiarlo in base alle loro reali esigenze. Al contrario, l'interfaccia definisce solo il comportamento, non l'attributo. L'unico motivo per inserire le variabili nell'interfaccia è usarle come aspetti correlati a tale interfaccia. Tuttavia, questa non è una buona pratica secondo il seguente estratto:

"Posizionare le costanti in un'interfaccia era una tecnica popolare nei primi tempi di Java, ma ora molti lo considerano un uso sgradevole delle interfacce, poiché le interfacce dovrebbero occuparsi dei servizi forniti da un oggetto, non dei suoi dati. Inoltre, le costanti utilizzate da una classe sono in genere un dettaglio di implementazione, ma inserendoli in un'interfaccia li promuove all'API pubblica della classe. "

Ho anche provato a mettere statico o non fa alcuna differenza. Il codice è il seguente:

public interface Addable {
    static int count = 6;

    public int add(int i);

}

public class Impl implements Addable {

    @Override
    public int add(int i) {
        return i+count;
    }
}

public class Test {

    public static void main(String... args) {
        Impl impl = new Impl();

        System.out.println(impl.add(4));
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.