Perché le variabili di interfaccia sono statiche e finali per impostazione predefinita in Java?
Perché le variabili di interfaccia sono statiche e finali per impostazione predefinita in Java?
Risposte:
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.
static
modificatore è 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 interface
non possa essere istanziato direttamente: puoi comunque avere istanze di classi che implementano il interface
ed è 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 final
significa.
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 !!!
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.
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.
( Questa non è una risposta filosofica ma più di una pratica ). Il requisito per il static
modificatore è 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 interface
campi 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 interface
proprietà non è diventata esplicitamente final
da 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 Actionable
altera 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 NuclearAction
può essere influenzato da un'altra classe CleanAction
, quando performAction()
viene invocata dopo CleanAction
l'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 interface
utilizzerà queste variabili, devono implicitamente esserlo final
.
Perché qualsiasi altra cosa fa parte dell'implementazione e le interfacce non possono contenere alcuna implementazione.
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.
static final
prima della variabile che in realtà è statica e finale.
statico - perché l'interfaccia non può avere alcuna istanza. e finale - perché non abbiamo bisogno di cambiarlo.
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
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
Un'interfaccia è un contratto tra due parti invariante, scolpito nella pietra, quindi definitivo. Vedi Design per contratto .
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.
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 final
quale è diverso da una variabile di istanza.
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.
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.
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));
}
}