Qual è la differenza principale tra una classe interna e una classe nidificata statica in Java? La progettazione / implementazione gioca un ruolo nella scelta di uno di questi?
Qual è la differenza principale tra una classe interna e una classe nidificata statica in Java? La progettazione / implementazione gioca un ruolo nella scelta di uno di questi?
Risposte:
Dal tutorial Java :
Le classi nidificate sono divise in due categorie: statiche e non statiche. Le classi nidificate dichiarate statiche vengono semplicemente chiamate classi nidificate statiche. Le classi nidificate non statiche sono chiamate classi interne.
Alle classi nidificate statiche si accede utilizzando il nome della classe allegato:
OuterClass.StaticNestedClass
Ad esempio, per creare un oggetto per la classe nidificata statica, utilizzare questa sintassi:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Gli oggetti che sono istanze di una classe interna esistono all'interno di un'istanza della classe esterna. Considera le seguenti classi:
class OuterClass {
...
class InnerClass {
...
}
}
Un'istanza di InnerClass può esistere solo all'interno di un'istanza di OuterClass e ha accesso diretto ai metodi e ai campi dell'istanza che la racchiude.
Per creare un'istanza di una classe interna, è innanzitutto necessario creare un'istanza della classe esterna. Quindi, crea l'oggetto interno all'interno dell'oggetto esterno con questa sintassi:
OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
vedi: Tutorial Java - Classi nidificate
Per completezza notare che esiste anche qualcosa come una classe interna senza un'istanza chiusa :
class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}
Qui, new A() { ... }
è una classe interna definita in un contesto statico e non ha un'istanza chiusa.
import OuterClass.StaticNestedClass;
quindi riferimento alla classe proprio come OuterClass.
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
?
Il tutorial Java dice :
Terminologia: le classi nidificate sono divise in due categorie: statiche e non statiche. Le classi nidificate dichiarate statiche vengono semplicemente chiamate classi nidificate statiche. Le classi nidificate non statiche sono chiamate classi interne.
Nel linguaggio comune, i termini "nidificato" e "interno" sono usati in modo intercambiabile dalla maggior parte dei programmatori, ma userò il termine corretto "classe nidificata" che copre sia interno che statico.
Le classi possono essere nidificate all'infinito , ad es. La classe A può contenere la classe B che contiene la classe C che contiene la classe D, ecc. Tuttavia, più di un livello di annidamento delle classi è raro, poiché generalmente è un progetto errato.
Esistono tre motivi per cui potresti creare una classe nidificata:
Esistono quattro tipi di classe nidificata in Java . In breve, sono:
Permettetemi di elaborare in modo più dettagliato.
Le classi statiche sono il tipo più semplice da comprendere perché non hanno nulla a che fare con le istanze della classe contenente.
Una classe statica è una classe dichiarata come membro statico di un'altra classe. Proprio come gli altri membri statici, una classe di questo tipo è in realtà solo un appendiabiti che utilizza la classe contenitore come suo spazio dei nomi, ad esempio la classe Goat dichiarata come membro statico della classe Rhino nel pacchetto pizza è conosciuta con il nome pizza.Rhino.Goat .
package pizza;
public class Rhino {
...
public static class Goat {
...
}
}
Francamente, le classi statiche sono una caratteristica piuttosto inutile perché le classi sono già divise in spazi dei nomi dai pacchetti. L'unico vero motivo immaginabile per creare una classe statica è che una tale classe ha accesso ai membri statici privati della sua classe contenente, ma trovo che questa sia una giustificazione piuttosto scadente per l'esistenza della funzione di classe statica.
Una classe interna è una classe dichiarata come membro non statico di un'altra classe:
package pizza;
public class Rhino {
public class Goat {
...
}
private void jerry() {
Goat g = new Goat();
}
}
Come con una classe statica, la classe interna è conosciuta come qualificata dal suo nome di classe contenente, pizza.Rhino.Goat , ma all'interno della classe di contenimento, può essere conosciuta con il suo nome semplice. Tuttavia, ogni esempio di una classe interna è legato ad una determinata condizione di classe contenente: sopra, la capra creato in Jerry , è implicitamente legata alla Rhino esempio questo in Jerry . Altrimenti, rendiamo esplicita l'istanza di Rhino associata quando istanziamo Goat :
Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();
(Nota che ti riferisci al tipo interno come solo Capra nella strana nuova sintassi: Java deduce il tipo contenitivo dalla parte del rinoceronte . E sì, il nuovo rhino.Goat () avrebbe avuto più senso anche per me.)
Cosa ci guadagna questo? Bene, l'istanza di classe interna ha accesso ai membri di istanza dell'istanza di classe contenente. Questi membri dell'istanza che li racchiudono vengono citati all'interno della classe interna solo tramite i loro nomi semplici, non tramite questo ( ciò nella classe interna si riferisce all'istanza della classe interna, non all'istanza della classe contenente associata):
public class Rhino {
private String barry;
public class Goat {
public void colin() {
System.out.println(barry);
}
}
}
Nella classe interna, è possibile fare riferimento a questo della classe contenente come Rhino.this , ed è possibile utilizzare questo per fare riferimento ai suoi membri, ad esempio Rhino.this.barry .
Una classe interna locale è una classe dichiarata nel corpo di un metodo. Tale classe è nota solo nel suo metodo di contenimento, quindi può solo essere istanziata e avere accesso ai suoi membri nel suo metodo di contenimento. Il vantaggio è che un'istanza di classe interna locale è collegata e può accedere alle variabili locali finali del suo metodo di contenimento. Quando l'istanza utilizza un locale finale del suo metodo di contenimento, la variabile conserva il valore che deteneva al momento della creazione dell'istanza, anche se la variabile è andata fuori dal campo di applicazione (si tratta effettivamente della versione grezza e limitata di chiusure di Java).
Poiché una classe interna locale non è né membro di una classe o pacchetto, non viene dichiarata con un livello di accesso. (Sii chiaro, tuttavia, che i suoi membri hanno livelli di accesso come in una classe normale.)
Se una classe interna locale viene dichiarata in un metodo di istanza, un'istanza della classe interna è legata all'istanza detenuta dal metodo contenitore presente al momento della creazione dell'istanza, e quindi i membri dell'istanza della classe contenitore sono accessibili come in un'istanza classe interiore. Una classe interna locale viene istanziata semplicemente tramite il suo nome, ad esempio la classe interna locale Cat viene istanziata come nuovo Cat () , non nuovo this.Cat () come ci si potrebbe aspettare.
Una classe interna anonima è un modo sintatticamente conveniente di scrivere una classe interna locale. Più comunemente, una classe interna locale viene istanziata al massimo una volta ogni volta che viene eseguito il suo metodo di contenimento. Sarebbe bello, quindi, se potessimo combinare la definizione di classe interna locale e la sua singola istanza in una comoda forma di sintassi, e sarebbe anche bello se non dovessimo pensare a un nome per la classe (meno inutili nomi contenuti nel codice, meglio è). Una classe interna anonima consente entrambe queste cose:
new *ParentClassName*(*constructorArgs*) {*members*}
Questa è un'espressione che restituisce una nuova istanza di una classe senza nome che estende ParentClassName . Non puoi fornire il tuo costruttore; piuttosto, ne viene fornito uno implicitamente che chiama semplicemente il super costruttore, quindi gli argomenti forniti devono adattarsi al super costruttore. (Se il genitore contiene più costruttori, viene chiamato quello "più semplice", "più semplice" come determinato da un insieme piuttosto complesso di regole che non vale la pena di imparare in dettaglio - presta attenzione a ciò che NetBeans o Eclipse ti dicono.)
In alternativa, puoi specificare un'interfaccia per implementare:
new *InterfaceName*() {*members*}
Tale dichiarazione crea una nuova istanza di una classe senza nome che estende Object e implementa InterfaceName . Ancora una volta, non è possibile fornire il proprio costruttore; in questo caso, Java fornisce implicitamente un costruttore no-arg, do-nothing (quindi non ci saranno mai argomenti di costruzione in questo caso).
Anche se non è possibile assegnare a una classe interna anonima un costruttore, è comunque possibile eseguire qualsiasi impostazione desiderata utilizzando un blocco di inizializzazione (un blocco {} posizionato al di fuori di qualsiasi metodo).
Sii chiaro che una classe interna anonima è semplicemente un modo meno flessibile di creare una classe interna locale con un'istanza. Se si desidera una classe interna locale che implementa più interfacce o che implementa interfacce estendendo una classe diversa da Object o che specifica il proprio costruttore, si è bloccati nel creare una classe interna locale denominata regolare.
Non credo che la vera differenza sia diventata chiara nelle risposte sopra.
Prima di ottenere i termini giusti:
La risposta di Martin è giusta finora. Tuttavia, la vera domanda è: qual è lo scopo di dichiarare statica una classe nidificata o no?
Si utilizzano classi nidificate statiche se si desidera solo mantenere le classi insieme se appartengono per via topica insieme o se la classe nidificata viene utilizzata esclusivamente nella classe che la racchiude. Non esiste alcuna differenza semantica tra una classe nidificata statica e ogni altra classe.
Le classi nidificate non statiche sono una bestia diversa. Simile alle classi interne anonime, tali classi nidificate sono in realtà chiusure. Ciò significa che acquisiscono il loro ambito circostante e la loro istanza che lo racchiude e lo rendono accessibile. Forse un esempio lo chiarirà. Vedi questo troncone di un contenitore:
public class Container {
public class Item{
Object data;
public Container getContainer(){
return Container.this;
}
public Item(Object data) {
super();
this.data = data;
}
}
public static Item create(Object data){
// does not compile since no instance of Container is available
return new Item(data);
}
public Item createSubItem(Object data){
// compiles, since 'this' Container is available
return new Item(data);
}
}
In questo caso, si desidera avere un riferimento da un elemento figlio al contenitore padre. Utilizzando una classe nidificata non statica, questo funziona senza alcun lavoro. È possibile accedere all'istanza inclusa di Container con la sintassi Container.this
.
Altre spiegazioni hardcore seguenti:
Se guardi i bytecode Java generati dal compilatore per una classe nidificata (non statica), potrebbe diventare ancora più chiaro:
// class version 49.0 (49)
// access flags 33
public class Container$Item {
// compiled from: Container.java
// access flags 1
public INNERCLASS Container$Item Container Item
// access flags 0
Object data
// access flags 4112
final Container this$0
// access flags 1
public getContainer() : Container
L0
LINENUMBER 7 L0
ALOAD 0: this
GETFIELD Container$Item.this$0 : Container
ARETURN
L1
LOCALVARIABLE this Container$Item L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 1
public <init>(Container,Object) : void
L0
LINENUMBER 12 L0
ALOAD 0: this
ALOAD 1
PUTFIELD Container$Item.this$0 : Container
L1
LINENUMBER 10 L1
ALOAD 0: this
INVOKESPECIAL Object.<init>() : void
L2
LINENUMBER 11 L2
ALOAD 0: this
ALOAD 2: data
PUTFIELD Container$Item.data : Object
RETURN
L3
LOCALVARIABLE this Container$Item L0 L3 0
LOCALVARIABLE data Object L0 L3 2
MAXSTACK = 2
MAXLOCALS = 3
}
Come puoi vedere, il compilatore crea un campo nascosto Container this$0
. Questo è impostato nel costruttore che ha un parametro aggiuntivo di tipo Contenitore per specificare l'istanza che la contiene. Non è possibile visualizzare questo parametro nell'origine ma il compilatore lo genera implicitamente per una classe nidificata.
L'esempio di Martin
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
verrebbe quindi compilato per una chiamata di qualcosa di simile (in bytecodes)
new InnerClass(outerObject)
Per amor di completezza:
Una classe anonima è un esempio perfetto di una classe nidificata non statica a cui non è associato alcun nome e alla quale non è possibile fare riferimento in un secondo momento.
Penso che nessuna delle risposte sopra ti spieghi la vera differenza tra una classe nidificata e una classe annidata statica in termini di progettazione dell'applicazione:
Una classe nidificata può essere non statica o statica e in ogni caso è una classe definita all'interno di un'altra classe . Una classe nidificata dovrebbe esistere solo per servire è la classe che racchiude , se una classe nidificata è utile per altre classi (non solo quella che lo racchiude), dovrebbe essere dichiarata come classe di livello superiore.
Classe nidificata non statica : è implicitamente associata all'istanza che racchiude la classe contenente, ciò significa che è possibile invocare metodi e accedere alle variabili dell'istanza che lo racchiude. Un uso comune di una classe nidificata non statica è la definizione di una classe Adapter.
Classe nidificata statica : impossibile accedere all'istanza di classe racchiusa e invocare metodi su di essa, pertanto deve essere utilizzata quando la classe nidificata non richiede l'accesso a un'istanza della classe che la racchiude. Un uso comune della classe nidificata statica consiste nell'implementare un componente dell'oggetto esterno.
Quindi la differenza principale tra i due dal punto di vista del design è: la classe nidificata non statica può accedere all'istanza della classe container, mentre statica no .
In termini semplici abbiamo bisogno di classi nidificate principalmente perché Java non fornisce chiusure.
Le classi nidificate sono classi definite all'interno del corpo di un'altra classe che la racchiude. Sono di due tipi: statici e non statici.
Sono trattati come membri della classe che lo racchiude, quindi è possibile specificare uno dei quattro identificatori di accesso - private, package, protected, public
. Non abbiamo questo lusso con classi di alto livello, che possono solo essere dichiarate public
o riservate al pacchetto.
Le classi interne ovvero le classi non stack hanno accesso ad altri membri della classe superiore, anche se sono dichiarate private mentre le classi nidificate statiche non hanno accesso ad altri membri della classe superiore.
public class OuterClass {
public static class Inner1 {
}
public class Inner2 {
}
}
Inner1
è la nostra classe interna statica ed Inner2
è la nostra classe interna che non è statica. La differenza fondamentale tra loro, non è possibile creare Inner2
un'istanza senza un esterno in cui è possibile creare un Inner1
oggetto in modo indipendente.
Quando useresti la classe interna?
Pensa a una situazione in cui Class A
e Class B
sono collegati, Class B
deve accedere ai Class A
membri ed Class B
è legato solo a Class A
. Classi interiori entrano in scena.
Per creare un'istanza della classe interna, è necessario creare un'istanza della classe esterna.
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
o
OuterClass.Inner2 inner = new OuterClass().new Inner2();
Quando useresti la classe interna statica?
Definiresti una classe interna statica quando sai che non ha alcuna relazione con l'istanza della classe / classe superiore inclusa. Se la tua classe interna non usa metodi o campi della classe esterna, è solo uno spreco di spazio, quindi rendila statica.
Ad esempio, per creare un oggetto per la classe nidificata statica, utilizzare questa sintassi:
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
Il vantaggio di una classe nidificata statica è che non ha bisogno di un oggetto della classe / classe superiore contenente per funzionare. Questo può aiutarti a ridurre il numero di oggetti creati dalla tua applicazione in fase di esecuzione.
OuterClass.Inner2 inner = outer.new Inner2();
?
static inner
è una contraddizione in termini.
Ecco le differenze e le somiglianze chiave tra la classe interna Java e la classe nidificata statica.
Spero che sia d'aiuto!
Associato all'istanza della classe che racchiude, quindi per creare un'istanza è necessario innanzitutto un'istanza della classe esterna (notare il nuovo posto della parola chiave):
Outerclass.InnerClass innerObject = outerObject.new Innerclass();
Non è possibile definire alcun membro statico stesso
Impossibile accedere ai metodi o ai campi dell'istanza di classe esterna
Non associato a nessuna istanza della classe che racchiude Quindi per istanziarlo:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Secondo la documentazione Oracle ci sono diversi motivi ( documentazione completa ):
È un modo per raggruppare logicamente le classi che vengono utilizzate solo in una posizione: se una classe è utile solo per un'altra classe, è logico incorporarla in quella classe e tenere insieme le due cose. La nidificazione di tali "classi di supporto" rende il loro pacchetto più snello.
Aumenta l'incapsulamento: considera due classi di livello superiore, A e B, dove B ha bisogno di accedere ai membri di A che altrimenti sarebbero dichiarati privati. Nascondendo la classe B all'interno della classe A, i membri di A possono essere dichiarati privati e B può accedervi. Inoltre, B stessa può essere nascosta dal mondo esterno.
Può portare a un codice più leggibile e gestibile : l' annidamento di piccole classi all'interno di classi di livello superiore posiziona il codice più vicino a dove viene utilizzato.
Penso che la convenzione generalmente seguita sia questa:
Tuttavia, alcuni altri punti da ricordare sono:
Le classi di livello superiore e la classe nidificata statica sono semanticamente uguali, tranne che nel caso della classe nidificata statica può fare riferimento statico a campi / metodi statici privati della sua classe [parent] esterna e viceversa.
Le classi interne hanno accesso alle variabili di istanza dell'istanza che racchiude la classe [parent] esterna. Tuttavia, non tutte le classi interne hanno istanze racchiuse, ad esempio le classi interne in contesti statici, come una classe anonima utilizzata in un blocco di inizializzatore statico, no.
La classe anonima per impostazione predefinita estende la classe genitore o implementa l'interfaccia genitore e non vi è alcuna clausola ulteriore per estendere qualsiasi altra classe o implementare altre interfacce. Così,
new YourClass(){};
si intende class [Anonymous] extends YourClass {}
new YourInterface(){};
si intende class [Anonymous] implements YourInterface {}
Sento che la domanda più grande che rimane aperta quale usare e quando? Bene, dipende principalmente dallo scenario con cui hai a che fare, ma leggere la risposta data da @jrudolph può aiutarti a prendere qualche decisione.
Classe nidificata: classe all'interno della classe
tipi:
Differenza:
Classe nidificata non statica [Classe interna]
Nella classe nidificata non statica esiste un oggetto della classe interna all'interno dell'oggetto della classe esterna. In modo che quel membro di dati della classe esterna sia accessibile alla classe interna. Quindi per creare un oggetto di classe interna dobbiamo prima creare un oggetto di classe esterna.
outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass();
Classe nidificata statica
Nella classe nidificata statica, l'oggetto della classe interna non ha bisogno dell'oggetto della classe esterna, poiché la parola "statico" indica che non è necessario creare l'oggetto.
class outerclass A {
static class nestedclass B {
static int x = 10;
}
}
Se si desidera accedere a x, quindi scrivere il seguente metodo interno
outerclass.nestedclass.x; i.e. System.out.prinltn( outerclass.nestedclass.x);
L'istanza della classe interna viene creata quando viene creata l'istanza della classe esterna. Pertanto i membri e i metodi della classe interna hanno accesso ai membri e ai metodi dell'istanza (oggetto) della classe esterna. Quando l'istanza della classe esterna non rientra nell'ambito, anche le istanze della classe interna cessano di esistere.
La classe nidificata statica non ha un'istanza concreta. Viene appena caricato quando viene utilizzato per la prima volta (proprio come i metodi statici). È un'entità completamente indipendente, i cui metodi e variabili non hanno alcun accesso alle istanze della classe esterna.
Le classi nidificate statiche non sono accoppiate con l'oggetto esterno, sono più veloci e non occupano memoria heap / stack, perché non è necessario creare un'istanza di tale classe. Pertanto, la regola empirica è provare a definire la classe nidificata statica, con l'ambito il più limitato possibile (privato> = classe> = protetta> = pubblica), quindi convertirla in classe interna (rimuovendo l'identificatore "statico") e allentare l'ambito, se è davvero necessario.
Esiste una sottigliezza sull'uso delle classi statiche nidificate che potrebbe essere utile in determinate situazioni.
Mentre gli attributi statici vengono istanziati prima che la classe venga istanziata tramite il suo costruttore, gli attributi statici all'interno delle classi statiche nidificate non sembrano essere istanziati fino a quando non viene invocato il costruttore della classe, o almeno fino a quando non viene fatto riferimento per la prima volta agli attributi, anche se sono contrassegnati come "finali".
Considera questo esempio:
public class C0 {
static C0 instance = null;
// Uncomment the following line and a null pointer exception will be
// generated before anything gets printed.
//public static final String outerItem = instance.makeString(98.6);
public C0() {
instance = this;
}
public String makeString(int i) {
return ((new Integer(i)).toString());
}
public String makeString(double d) {
return ((new Double(d)).toString());
}
public static final class nested {
public static final String innerItem = instance.makeString(42);
}
static public void main(String[] argv) {
System.out.println("start");
// Comment out this line and a null pointer exception will be
// generated after "start" prints and before the following
// try/catch block even gets entered.
new C0();
try {
System.out.println("retrieve item: " + nested.innerItem);
}
catch (Exception e) {
System.out.println("failed to retrieve item: " + e.toString());
}
System.out.println("finish");
}
}
Anche se "nidificato" e "innerItem" sono entrambi dichiarati "finali statici". l'impostazione di nested.innerItem non ha luogo fino a quando la classe non viene istanziata (o almeno fino a quando non viene fatto riferimento all'elemento statico nidificato per la prima volta), come puoi vedere tu stesso commentando e commentando le righe a cui faccio riferimento, sopra. Lo stesso non vale per 'outerItem'.
Almeno questo è quello che vedo in Java 6.0.
I termini sono usati in modo intercambiabile. Se si vuole essere davvero pedanti su di esso, allora si potrebbe definire la "classe annidata" per fare riferimento a una classe interna statica, uno che non ha alcun esempio di cinta. Nel codice, potresti avere qualcosa del genere:
public class Outer {
public class Inner {}
public static class Nested {}
}
Tuttavia, questa non è una definizione ampiamente accettata.
Nel caso della creazione dell'istanza, l'istanza della classe interna non statica viene creata con il riferimento all'oggetto della classe esterna in cui è definita. Ciò significa che ha un'istanza inclusiva. Ma l'istanza della classe interna statica viene creata con il riferimento della classe esterna, non con il riferimento all'oggetto della classe esterna. Ciò significa che non ha inclusione inclusiva.
Per esempio:
class A
{
class B
{
// static int x; not allowed here…..
}
static class C
{
static int x; // allowed here
}
}
class Test
{
public static void main(String… str)
{
A o=new A();
A.B obj1 =o.new B();//need of inclosing instance
A.C obj2 =new A.C();
// not need of reference of object of outer class….
}
}
Non penso che ci sia molto da aggiungere qui, la maggior parte delle risposte spiega perfettamente le differenze tra classe nidificata statica e classi interne. Tuttavia, considerare il seguente problema quando si utilizzano classi nidificate vs classi interne. Come menzionato in un paio di risposte, le classi interne non possono essere istanziate senza e istanza della loro classe che racchiude, il che significa che tengono un puntatore all'istanza della loro classe che racchiude che può portare a overflow di memoria o stack overflow a causa del fatto che il GC non sarà in grado di eseguire la garbage collection delle classi che la racchiudono anche se non vengono più utilizzate. Per chiarire questo, controlla il codice seguente:
public class Outer {
public class Inner {
}
public Inner inner(){
return new Inner();
}
@Override
protected void finalize() throws Throwable {
// as you know finalize is called by the garbage collector due to destroying an object instance
System.out.println("I am destroyed !");
}
}
public static void main(String arg[]) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
// out instance is no more used and should be garbage collected !!!
// However this will not happen as inner instance is still alive i.e used, not null !
// and outer will be kept in memory until inner is destroyed
outer = null;
//
// inner = null;
//kick out garbage collector
System.gc();
}
Se rimuovi il commento su // inner = null;
Il programma pubblicherà " Sono distrutto! ", Ma mantenendo questo commento non lo farà.
Il motivo è che l'istanza interna bianca fa ancora riferimento a GC non può raccoglierla e poiché fa riferimento (ha un puntatore a) all'istanza esterna non viene raccolta. Avere abbastanza oggetti di questo tipo nel progetto e esaurire la memoria.
Rispetto alle classi interne statiche che non contengono un punto all'istanza della classe interna perché non è correlata all'istanza ma alla classe. Il programma sopra può stampare " Sono distrutto! " Se si rende la classe Inner statica e istanziata conOuter.Inner i = new Outer.Inner();
La classe nidificata è un termine molto generale: ogni classe che non è di livello superiore è una classe nidificata. Una classe interna è una classe nidificata non statica. Joseph Darcy ha scritto una bella spiegazione sulle classi nidificate, interne, dei membri e di livello superiore .
Ummm ... una classe interna È una classe nidificata ... intendi classe anonima e classe interna?
Modifica: se in realtà intendevi interno vs anonimo ... una classe interna è solo una classe definita all'interno di una classe come:
public class A {
public class B {
}
}
Considerando che una classe anonima è un'estensione di una classe definita in modo anonimo, quindi non viene definita alcuna classe "effettiva, come in:
public class A {
}
A anon = new A() { /* you could change behavior of A here */ };
Ulteriore modifica:
Wikipedia afferma che c'è una differenza in Java, ma ho lavorato con Java per 8 anni, ed è il primo che ho sentito una tale distinzione ... per non parlare del fatto che non ci sono riferimenti per sostenere il reclamo ... in basso linea, una classe interna è una classe definita all'interno di una classe (statica o no) e nidificata è solo un altro termine per indicare la stessa cosa.
Esiste una sottile differenza tra classe nidificata statica e non statica ... in sostanza le classi interne non statiche hanno accesso implicito ai campi di istanza e ai metodi della classe che lo racchiude (quindi non possono essere costruite in un contesto statico, sarà un compilatore errore). Le classi nidificate statiche, d'altra parte, non hanno accesso implicito ai campi e ai metodi dell'istanza e POSSONO essere costruite in un contesto statico.
Targeting per studente, che è alle prime armi in Java e / o classi nidificate
Le classi nidificate possono essere:
1. Classi nidificate statiche.
2. Classi nidificate non statiche. (noto anche come classi interne ) => Ricorda questo
1.
Esempio di classi interne :
class OuterClass {
/* some code here...*/
class InnerClass { }
/* some code here...*/
}
Le classi interne sono sottoinsiemi di classi nidificate:
Specialità di classe interna:
2. Classi annidate statiche:
Esempio:
class EnclosingClass {
static class Nested {
void someMethod() { System.out.println("hello SO"); }
}
}
Caso 1: istanziazione di una classe nidificata statica da una classe non chiusa
class NonEnclosingClass {
public static void main(String[] args) {
/*instantiate the Nested class that is a static
member of the EnclosingClass class:
*/
EnclosingClass.Nested n = new EnclosingClass.Nested();
n.someMethod(); //prints out "hello"
}
}
Caso 2: istanza di una classe nidificata statica da una classe che la racchiude
class EnclosingClass {
static class Nested {
void anotherMethod() { System.out.println("hi again"); }
}
public static void main(String[] args) {
//access enclosed class:
Nested n = new Nested();
n.anotherMethod(); //prints out "hi again"
}
}
Specialità di lezioni statiche:
Conclusione:
domanda: qual è la differenza principale tra una classe interna e una classe annidata statica in Java?
Risposta: basta esaminare le specifiche di ciascuna classe sopra menzionata.
La classe interna e la classe statica nidificata in Java sono entrambe classi dichiarate all'interno di un'altra classe, nota come classe di livello superiore in Java. Nella terminologia Java, se si dichiara una classe nidificata statica, verrà chiamata classe statica nidificata in Java mentre la classe nidificata non statica viene semplicemente denominata Classe interna.
Che cos'è la classe interna in Java?
Qualsiasi classe che non sia di livello superiore o dichiarata all'interno di un'altra classe è nota come classe nidificata e al di fuori di quelle classi nidificate, la classe dichiarata non statica è conosciuta come classe interna in Java. ci sono tre tipi di classe interna in Java:
1) Classe interna locale - è dichiarata all'interno di un blocco o metodo di codice.
2) Classe interna anonima - è una classe che non ha un nome a cui fare riferimento e inizializzata nello stesso posto in cui viene creata.
3) Classe interna membro: viene dichiarata come membro non statico della classe esterna.
public class InnerClassTest {
public static void main(String args[]) {
//creating local inner class inside method i.e. main()
class Local {
public void name() {
System.out.println("Example of Local class in Java");
}
}
//creating instance of local inner class
Local local = new Local();
local.name(); //calling method from local inner class
//Creating anonymous inner class in Java for implementing thread
Thread anonymous = new Thread(){
@Override
public void run(){
System.out.println("Anonymous class example in java");
}
};
anonymous.start();
//example of creating instance of inner class
InnerClassTest test = new InnerClassTest();
InnerClassTest.Inner inner = test.new Inner();
inner.name(); //calling method of inner class
}
//Creating Inner class in Java
private class Inner{
public void name(){
System.out.println("Inner class example in java");
}
}
}
Cos'è la classe statica nidificata in Java?
La classe statica nidificata è un'altra classe dichiarata all'interno di una classe come membro e resa statica. La classe statica nidificata viene inoltre dichiarata come membro della classe esterna e può essere privata, pubblica o protetta come qualsiasi altro membro. Uno dei principali vantaggi della classe statica nidificata rispetto alla classe interna è che l'istanza della classe statica nidificata non è collegata a nessuna istanza chiusa della classe esterna. Inoltre non è necessaria alcuna istanza della classe esterna per creare un'istanza della classe statica nidificata in Java .
1) Può accedere a membri di dati statici di classe esterna compreso privato.
2) La classe nidificata statica non può accedere a un membro o metodo di dati non statici (istanza) .
public class NestedStaticExample {
public static void main(String args[]){
StaticNested nested = new StaticNested();
nested.name();
}
//static nested class in java
private static class StaticNested{
public void name(){
System.out.println("static nested class example in java");
}
}
}
Rif: classe interna e classe statica nidificata in Java con esempio
Penso che la gente qui dovrebbe notare che Poster: Classe Nest statica è solo la prima classe interna. Per esempio:
public static class A {} //ERROR
public class A {
public class B {
public static class C {} //ERROR
}
}
public class A {
public static class B {} //COMPILE !!!
}
Quindi, riassumendo, la classe statica non dipende dalla classe che contiene. Quindi, non possono andare in classe normale. (perché la classe normale necessita di un'istanza).
Quando dichiariamo una classe membro statica all'interno di una classe, è nota come classe nidificata di livello superiore o classe nidificata statica. Può essere dimostrato come di seguito:
class Test{
private static int x = 1;
static class A{
private static int y = 2;
public static int getZ(){
return B.z+x;
}
}
static class B{
private static int z = 3;
public static int getY(){
return A.y;
}
}
}
class TestDemo{
public static void main(String[] args){
Test t = new Test();
System.out.println(Test.A.getZ());
System.out.println(Test.B.getY());
}
}
Quando dichiariamo una classe membro non statica all'interno di una classe, questa è nota come classe interna. La classe interna può essere dimostrata come di seguito:
class Test{
private int i = 10;
class A{
private int i =20;
void display(){
int i = 30;
System.out.println(i);
System.out.println(this.i);
System.out.println(Test.this.i);
}
}
}
Di seguito è riportato un esempio di static nested class
e inner class
:
OuterClass.java
public class OuterClass {
private String someVariable = "Non Static";
private static String anotherStaticVariable = "Static";
OuterClass(){
}
//Nested classes are static
static class StaticNestedClass{
private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable";
//can access private variables declared in the outer class
public static void getPrivateVariableofOuterClass(){
System.out.println(anotherStaticVariable);
}
}
//non static
class InnerClass{
//can access private variables of outer class
public String getPrivateNonStaticVariableOfOuterClass(){
return someVariable;
}
}
public static void accessStaticClass(){
//can access any variable declared inside the Static Nested Class
//even if it private
String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable;
System.out.println(var);
}
}
OuterClassTest:
public class OuterClassTest {
public static void main(String[] args) {
//access the Static Nested Class
OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();
//test the private variable declared inside the static nested class
OuterClass.accessStaticClass();
/*
* Inner Class Test
* */
//Declaration
//first instantiate the outer class
OuterClass outerClass = new OuterClass();
//then instantiate the inner class
OuterClass.InnerClass innerClassExample = outerClass. new InnerClass();
//test the non static private variable
System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass());
}
}
Penso che nessuna delle risposte di cui sopra ti dia il vero esempio della differenza tra una classe nidificata e una classe nidificata statica in termini di progettazione dell'applicazione. E la principale differenza tra la classe nidificata statica e la classe interna è la possibilità di accedere al campo dell'istanza della classe esterna.
Diamo un'occhiata ai due seguenti esempi.
Classe di annidamento statico: un buon esempio di utilizzo di classi annidate statiche è il modello di generatore ( https://dzone.com/articles/design-patterns-the-builder-pattern ).
Per BankAccount utilizziamo una classe nidificata statica, principalmente perché
L'istanza della classe nido statica potrebbe essere creata prima della classe esterna.
Nel modello builder, il builder è una classe helper utilizzata per creare BankAccount.
public class BankAccount {
private long accountNumber;
private String owner;
...
public static class Builder {
private long accountNumber;
private String owner;
...
static public Builder(long accountNumber) {
this.accountNumber = accountNumber;
}
public Builder withOwner(String owner){
this.owner = owner;
return this;
}
...
public BankAccount build(){
BankAccount account = new BankAccount();
account.accountNumber = this.accountNumber;
account.owner = this.owner;
...
return account;
}
}
}
Classe interna: un uso comune delle classi interne è la definizione di un gestore eventi. https://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html
Per MyClass, utilizziamo la classe interna, principalmente perché:
MyAdapter di classe interna deve accedere al membro di classe esterno.
Nell'esempio, MyAdapter è associato solo a MyClass. Nessun'altra classe è correlata a MyAdapter. quindi è meglio organizzarli insieme senza usare una convenzione dei nomi
public class MyClass extends Applet {
...
someObject.addMouseListener(new MyAdapter());
...
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
...// Event listener implementation goes here...
...// change some outer class instance property depend on the event
}
}
}
Prima di tutto non esiste una classe del genere chiamata classe statica. L'uso del modificatore statico con la classe interna (chiamata come classe nidificata) afferma che è un membro statico della classe esterna, il che significa che possiamo accedervi come con altri membri statici e senza avere alcun istanza della classe esterna. (Che è il vantaggio di statico in origine.)
La differenza tra l'utilizzo della classe annidata e la normale classe interna è:
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
Per prima cosa possiamo creare un'istanza di Superclass quindi possiamo accedere a Inner.
Ma se Class è nidificata, la sintassi è:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
Che utilizza la sintassi statica come normale implementazione della parola chiave statica.
Il linguaggio di programmazione Java consente di definire una classe all'interno di un'altra classe. Tale classe viene chiamata classe nidificata ed è illustrata qui:
class OuterClass {
...
class NestedClass {
...
}
}
Le classi nidificate sono divise in due categorie: statiche e non statiche. Le classi nidificate dichiarate statiche sono chiamate classi nidificate statiche. Le classi nidificate non statiche sono chiamate classi interne. Una cosa da tenere a mente è che le classi nidificate non statiche (classi interne) hanno accesso ad altri membri della classe che la racchiude, anche se sono dichiarate private. Le classi nidificate statiche hanno accesso ad altri membri della classe che la racchiude solo se sono statiche. Non può accedere a membri non statici della classe esterna. Come per i metodi e le variabili di classe, una classe nidificata statica è associata alla sua classe esterna. Ad esempio, per creare un oggetto per la classe nidificata statica, utilizzare questa sintassi:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
Per creare un'istanza di una classe interna, è innanzitutto necessario creare un'istanza della classe esterna. Quindi, crea l'oggetto interno all'interno dell'oggetto esterno con questa sintassi:
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
Perché usiamo le classi nidificate
La differenza è che una dichiarazione di classe nidificata che è anche statica può essere istanziata al di fuori della classe che la racchiude.
Quando si dispone di una dichiarazione di classe nidificata non statica, nota anche come classe interna , Java non consente di creare un'istanza se non tramite la classe che la racchiude. L'oggetto creato dalla classe interna è collegato all'oggetto creato dalla classe esterna, quindi la classe interna può fare riferimento ai campi dell'esterno.
Ma se è statico, allora il collegamento non esiste, non è possibile accedere ai campi esterni (tranne tramite un riferimento ordinario come qualsiasi altro oggetto) e quindi è possibile creare un'istanza della classe nidificata da sola.
È piuttosto semplice, confrontando le classi locali statiche e le classi interne non statiche
Differenze:
Classe locale statica:
può accedere solo ai membri statici della classe esterna.
Impossibile avere inizializzatori statici
Non è possibile accedere direttamente dall'esterno della funzione in cui è dichiarata
Ho illustrato vari possibili scenari corretti ed errori che possono verificarsi nel codice java.
class Outter1 {
String OutStr;
Outter1(String str) {
OutStr = str;
}
public void NonStaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// below static attribute not permitted
// static String tempStatic1 = "static";
// below static with final attribute not permitted
// static final String tempStatic1 = "ashish";
// synchronized keyword is not permitted below
class localInnerNonStatic1 {
synchronized public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
public static void StaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// static attribute not permitted below
//static String tempStatic1 = "static";
// static with final attribute not permitted below
// static final String tempStatic1 = "ashish";
class localInnerNonStatic1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
// synchronized keyword is not permitted
static class inner1 {
static String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
public static void innerStaticMethod(String str11) {
// error in below step
str11 = temp1 +" india";
//str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
//}
}
//synchronized keyword is not permitted below
class innerNonStatic1 {
//This is important we have to keep final with static modifier in non
// static innerclass below
static final String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
synchronized public void innerMethod(String str11) {
tempNonStatic = tempNonStatic +" ...";
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// error in below step
public static void innerStaticMethod(String str11) {
// error in below step
// str11 = tempNonStatic +" india";
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
//}
}
}
item 22 : Favor static member classes over non static