Domanda

Perché non possiamo avere un metodo statico in un non-statico classe interna ?

Se faccio la classe interna statico funziona.Perché ?

È stato utile?

Soluzione

Poiché un'istanza di una classe interna è implicitamente associato a un'istanza della sua classe esterna, non può definire qualsiasi metodi statici stesso. Poiché una classe innestata statica non può fare riferimento direttamente alle variabili di istanza o metodi definiti nella classe di inclusione, li può usare solo attraverso un riferimento all'oggetto, è sicuro dichiarare metodi statici in una classe innestata statica.

Altri suggerimenti

Non c'è molto punto a consentire un metodo statico in una classe interna non statica; come si accedervi? Non è possibile accedere (almeno inizialmente) un'istanza classe interna non statica senza passare attraverso un'istanza classe esterna. Non c'è modo puramente statica di creare una classe interna non statica.

Per un Outer classe esterna, è possibile accedere a un metodo test() statico come questo:

Outer.test();

Per una statica Inner classe interna, è possibile accedere suo metodo innerTest() statico come questo:

Outer.Inner.innerTest();

Tuttavia, se Inner non è statico, ora non c'è modo puramente statica per fare riferimento al metodo innertest. classi interne non statici sono legati a una specifica istanza di loro classe esterna. Una funzione è diversa da una costante, in quanto un riferimento a Outer.Inner.CONSTANT è garantito per essere univoco in modo che un Outer.Inner.staticFunction(); funzione chiamata non è. Diciamo che avete Inner.staticFunction() che chiama getState(), che è definito in Outer. Se si tenta di richiamare quella funzione statica, ora avete un riferimento ambiguo per la classe interna. Cioè, sul quale istanza della classe interna non si richiama la funzione statica? Importa. Vedi, non c'è modo veramente statica fare riferimento a tale metodo statico, a causa del riferimento implicito l'oggetto esterno.

Paolo Bellora è corretto che i progettisti di linguaggi potrebbero hanno permesso questo. Essi dovrebbero in tal caso disabilitare accuratamente ogni accesso al riferimento implicito alla classe esterna in metodi statici della classe interna non statica. A questo punto, qual è il valore di questo essere una classe interna se non è possibile fare riferimento alla classe esterna, ad eccezione staticamente? E se l'accesso statica va bene, allora perché non dichiarare tutta la classe interna statica? Se è sufficiente fare la classe interna statica in sé, allora non avete implicito riferimento alla classe esterna, e non hanno più questa ambiguità.

Se effettivamente necessità i metodi statici in una classe interna non statica, allora probabilmente bisogno di ripensare il vostro disegno.

Ho una teoria, che può o non può essere corretta.

In primo luogo, si dovrebbe sapere alcune cose su come le classi interne sono implementate in Java. Supponiamo che hai questa classe:

class Outer {
    private int foo = 0;
    class Inner implements Runnable {
        public void run(){ foo++; }
    }
    public Runnable newFooIncrementer(){ return new Inner(); }
}

Quando si compila il bytecode generato sarà come se hai scritto qualcosa di simile:

class Outer {
    private int foo = 0;
    static class Inner implements Runnable {
        private final Outer this$0;
        public Inner(Outer outer){
            this$0 = outer;
        }
        public void run(){ this$0.foo++; }
    }
    public Runnable newFooIncrementer(){ return new Inner(this); }
}

Ora, se abbiamo fatto consentire metodi statici in classi interne non statici, si potrebbe desiderare di fare qualcosa di simile.

class Outer {
    private int foo = 0;
    class Inner {
        public static void incrFoo(){ foo++; }
    }
}

... che sembra abbastanza ragionevole, come la classe Inner sembra avere un'incarnazione per istanza Outer. Ma, come abbiamo visto sopra, le classi interne non statici in realtà sono lo zucchero sintattico per le classi statiche "interiori", così l'ultimo esempio potrebbe essere approssimativamente equivalente a:

class Outer {
    private int foo = 0;
    static class Inner {
        private final Outer this$0;
        public Inner(Outer outer){
            this$0 = outer;
        }
        public static void incrFoo(){ this$0.foo++; }
    }
}

... che chiaramente non funziona, dal momento che è this$0 non statico. Questa sorta di spiega perché i metodi statici non sono ammessi (anche se si potrebbe fare l'argomento che si potrebbe consentire metodi statici finché essi non fanno riferimento all'oggetto racchiude), e perché non si può avere campi statici non definitive ( sarebbe intuitivo se istanze di classi interne non statici di diversi oggetti condivisi "stato statico"). Ciò spiega anche perché i campi finali sono ammesso (a patto che non fanno riferimento l'oggetto contenitore).

L'unico motivo è "non deve", quindi, perché preoccuparsi per il supporto?

Dal punto di vista sintattico,non c'è alcuna ragione per vietare una classe interna da avere i membri statici.Anche se un'istanza di Inner è associata a un'istanza di Outer, è comunque possibile utilizzare Outer.Inner.myStatic per fare riferimento a un membro statico di Inner se java decide di farlo.

Se avete bisogno di condividere qualcosa tra tutte le istanze di Inner, si può solo mettere in Outer come membri statici.Questo non è peggio di utilizzare i membri statici in Inner, dove Outer può ancora accedere a qualsiasi membro privato di Inner comunque(non migliorare incapsulamento).

Se avete bisogno di condividere qualcosa tra tutte le istanze di Inner creato da uno outer oggetto,si rende più senso per la loro messa in Outer classe come soci ordinari.

Io non condivido l'opinione che "statico classe nidificata è praticamente solo una classe di livello superiore".Penso che sia meglio davvero considerare statico classe nidificata/classe interna come una parte della classe esterna, perché si può accedere classe esterna privata di membri.E i membri della classe esterna sono "membri di una classe interna", come bene.Quindi non c'è bisogno di sostenere il membro statico in classe interna.Ordinaria/membro statico in classe esterna sarà sufficiente.

Risposta breve: Il modello mentale maggior parte dei programmatori hanno di come funziona campo di applicazione non è il modello usato da javac. Adattamento del modello più intuitiva avrebbe richiesto un grande cambiamento per il funzionamento javac.

Il motivo principale per cui i membri statici delle classi interne sono desiderabile è il codice è pulito - un membro statico usato solo da una classe interna deve vivere dentro, invece di dover essere collocato nella classe esterna. Prendere in considerazione:

class Outer {
   int outID;

   class Inner {
      static int nextID;
      int id = nextID++;

      String getID() {
         return outID + ":" + id;
      }
   }
}

Si consideri che cosa sta succedendo in getID () quando uso l'identificatore qualificato "outID". L'ambito in cui appare questo identificatore sembra qualcosa di simile:

Outer -> Inner -> getID()

Qui, ancora una volta perché questo è solo come funziona javac, il livello di "esterno" del campo di applicazione comprende sia membri statici e di istanza di esterno. Si tratta di confusione perché ci sono di solito detto di pensare alla parte statica di una classe come un altro livello del campo di applicazione:

Outer static -> Outer instance -> instanceMethod()
         \----> staticMethod()

In questo modo di pensare, naturalmente staticMethod () può vedere solo i membri statici di esterno. Ma se così fosse funziona come javac, quindi fa riferimento a una variabile di istanza in un metodo statico si tradurrebbe in un "nome non può essere risolto" errore. Ciò che realmente accade è che il nome si trova nel campo di applicazione, ma poi un ulteriore livello di calci check-in e capisce che il nome è stato dichiarato in un contesto istanza e viene fatto riferimento da un contesto statico.

OK, come si rapporta questo con le classi interne? Ingenuamente, pensiamo che non v'è alcuna ragione per classi interne non possono avere una portata statica, perché stiamo immaginando l'ambito di lavoro in questo modo:

Outer static -> Outer instance -> Inner instance -> getID()
         \------ Inner static ------^

In altre parole, le dichiarazioni statiche in dichiarazioni di classe e istanza interni in classe esterna sono entrambi in ambito entro il contesto della classe interna esempio, ma nessuno di questi è veramente annidati nell'altro; entrambi sono invece annidati nell'area statica di esterno.

Non è solo come funziona javac - v'è un unico livello di portata sia per i membri statici e di istanza, e la portata sempre rigorosamente nidi. Anche l'ereditarietà è implementato copiando dichiarazioni nella sottoclasse invece di ramificazione e la ricerca l'ambito superclasse.

Per sostenere i membri statici di classi interne javac avrebbe dovuto entrambi gli ambiti statici e di istanza dividere e il supporto di ramificazione e riaggiungono gerarchie ambito, o avrebbe dovuto estendere la sua semplice booleano idea "contesto statico" per cambiare per monitorare il tipo di contesto a tutti i livelli della classe annidata nel l'ambito corrente.

  

Perché non possiamo avere metodo statico in una classe interna non statica?

Nota. Una classe annidata non statico è noto come classe interna in modo da non avete non-static inner class come tale

Un esempio classe interna ha esistenza senza un corrispondente istanza della classe esterna. Una classe interna non può dichiarare i membri statici non compilare costanti di tempo. Se fosse permesso poi non ci sarebbe stata l'ambiguità sul significato di static. In quel caso non ci sarebbe stato certe confusioni:

  1. Vuol dire non v'è una sola istanza in VM?
  2. O una sola istanza per oggetto esterno?

Per questo motivo i progettisti probabilmente hanno preso la decisione di non manipolazione di questo problema a tutti.

  

Se faccio la classe interna statica funziona. Perché?

Anche in questo caso non si può fare una classe interna statica, piuttosto si può dichiarare una classe statica come nidificato. In questo caso classe innestata è in realtà parte di classe esterna e può avere membri statici senza alcun problema.

Questo argomento ha raccolto l'attenzione da molti, comunque cercherò di spiegare nel modo più semplice dei termini.

In primo luogo, con riferimento alla http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1 , una classe o interfaccia viene inizializzato immediatamente prima della prima occorrenza / invocazione di qualsiasi membro che è preceduto dalla parola chiave static.

  1. Quindi, se abbiamo messo con un membro statico all'interno di una classe interna, porterà alla inizializzazione della classe interna, non necessariamente la classe / racchiude esterno. Così, abbiamo ostacolano la sequenza di inizializzazione di classe.

  2. Anche considerare il fatto che una classe interna non statica è associata l'istanza di una classe contenitrice / esterno. Così, associando con un'istanza significherà, che la classe interna esisterà all'interno di un'istanza di classe esterno e sarà diverso tra i casi.

semplificazione del punto, al fine di accedere al membro static dobbiamo un'istanza di una classe esterno, da cui si ancora necessario creare un'istanza della classe interna non statica. I membri statici non sono supposti di essere vincolato alle istanze e quindi si riceverà un errore di compilazione.

Da: https://docs.oracle.com/javase /tutorial/java/javaOO/nested.html

  

Come metodi di istanza e variabili, una classe interna è associata ad un'istanza della sua classe contenitrice e ha accesso diretto ai metodi e campi dell'oggetto. Inoltre, poiché una classe interna è associato a un esempio, può non definire alcuna sé membri statici.

La spiegazione di Oracle è superficiale e handwavy. Dal momento che non c'è alcun motivo tecnico o sintattica per prevenire membri statici all'interno di una classe interna (è consentito in altri linguaggi come C #) motivazione i progettisti di Java era probabile sapore concettuale e / o una questione di convenienza tecnica.

Ecco la mia speculazione:

A differenza classi di primo livello, classi interne sono esempio-dipendente: un'istanza interna classe è associata a un'istanza di ogni una delle classi esterne e ha accesso diretto ai loro membri. Questa è la motivazione principale per averli in Java. Espressa altro modo: una classe interna è significato per istanziazione nel contesto di un'istanza classe esterna. Senza un'istanza classe esterna, una classe interna non dovrebbe essere più utilizzabile degli altri membri della classe esterna istanza. Facciamo riferimento a questo come il istanza dipendente spirito di classi interne.

La natura dei membri statici (che non orientata agli oggetti) si scontra con il esempio-dipendente spirito di classi interne (che è orientato agli oggetti) perché si può fare riferimento a / chiamare un membro statico di una classe interna senza un'istanza classe esterna utilizzando il nome qualificato classe interna.

Le variabili statiche in particolare, possono offendere in un altro modo: due istanze di una classe interna che sono associati con diverse istanze della classe esterna avrebbe condiviso le variabili statiche. Dal momento che le variabili sono una componente di stato, le due istanze della classe interna sarebbe, in effetti, condividono lo stato indipendentemente dalle istanze di classe esterni che stanno associati. Non è che è inaccettabile che le variabili statiche funzionano in questo modo (li accettiamo in Java come un compromesso ragionevole per OOP purezza), ma c'è senza dubbio un reato più profonda per essere avuto, consentendo loro in classi interne le cui istanze sono già accoppiato con istanze di classe esterni di progettazione. Proibire i membri statici all'interno di classi interne a favore della spirito esempio dipendenti miete il valore aggiunto di questo reato preempting OOP più profondo.

D'altra parte, tale reato si sostanzi costanti statiche, che non costituiscono significato stato e quindi queste sono ammissibili. Perché non vietare costanti statiche per la massima coerenza con il istanza dipendente spirito ? Forse perché costanti non bisogno per prendere più memoria del necessario (se sono costretti ad essere non statico poi sono copiati in ogni istanza di classe interna che è potenzialmente uno spreco). Altrimenti non riesco a immaginare il motivo per l'eccezione.

Non può essere solida ragionamento, ma IMO rende più senso di osservazione superficiale di Oracle in materia.

Una classe interna è qualcosa di completamente diverso da una classe innestata statica anche se entrambi sono simili nella sintassi. classi annidate statiche sono solo un mezzo per il raggruppamento che classi interne hanno una forte associazione - e l'accesso a tutti i valori di - loro classe esterna. Si dovrebbe essere sicuri perché si vuole utilizzare una classe interna e poi dovrebbe venire abbastanza naturale che uno si deve utilizzare. Se avete bisogno di dichiarare un metodo statico è probabilmente una classe innestata statica che si desidera in ogni caso.

supponiamo che ci siano due istanze di classe esterna e entrambi hanno un'istanza class.Now interna se classe interna ha un membro static allora manterrà solo una copia di quel membro in mucchio area.In questo caso entrambi gli oggetti della classe esterna sarà riferiscono a questa singola copia e possono alterare lo together.This può causare "sporco leggere" situazione quindi di evitare questo Java ha applicato questo punto di forza restriction.Another per supportare questo argomento è che permette java membri statici finali qui, quelli i cui valori possono 't essere cambiato da uno di oggetto classe esterna. Si prega di fare lasciami se sbaglio.

Prima di tutto perché qualcuno vuole definire il membro statico in una classe interna non statica? risposta è, in modo che il membro della classe esterno può utilizzare quelli membro statico con il nome di classe interna solo, giusto?

Ma per questo caso possiamo definire direttamente il membro in classe esterna. che saranno associati a tutte oggetto della classe interna, all'interno dell'istanza classe esterna.

come qui di seguito il codice,

public class Outer {

  class Inner {

    public static void method() {

    }

  }

}

può essere scritto come questo

public class Outer {

  void method() {

   }

   class Inner {


  }

}

Quindi, a mio parere non complicare il progettista codice Java non permette questa funzionalità o possiamo vedere questa funzionalità nelle future versioni con alcune caratteristiche.

cercare di trattare la classe come un campo normale, allora capirai.

//something must be static. Suppose something is an inner class, then it has static keyword which means it's a static class
Outer.something 

È inutile avere una classe interna membri statici, perché non sarà in grado di accedere, in primo luogo.

Pensate a questo, per accedere a un membro statico si utilizza className.nomeautore , nel nostro caso , dovrebbe essere qualcosa di simile nomeclasseesterna.innerclassName.nomeautore,,, ora non si vede perché innerclass deve essere statico....

È consentito metodi statici in classi annidate statiche. Ad esempio

public class Outer {

  public static class Inner {

    public static void method() {

    }
  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top