Domanda

Considera il seguente caso:

public class A {
  public A() { b = new B(); }
  B b;
  private class B { }
}

Da un avvertimento in Eclipse cito che:il compilatore Java emula il costruttore A.B() mediante un metodo di accesso sintetico.Suppongo che il compilatore ora vada avanti e crei un costruttore "sott'acqua" extra per B.

Sento che questo è piuttosto strano:perché la classe B non dovrebbe essere visibile come a.k.o.campo in A?E:significa che la classe B non è più privata in fase di esecuzione?E:perché la parola chiave protetta per la classe B si comporta in modo diverso?

public class A {
  public A() { b = new B(); }
  B b;
  protected class B { }
}
È stato utile?

Soluzione

Le classi interne sono essenzialmente un hack introdotto in Java 1.1. La JVM realtà non ha alcun concetto di una classe interna, e quindi il compilatore deve bodge esso. Il compilatore genera classe B "esterna" di classe A, ma nello stesso pacchetto, e poi aggiunge di accesso / costruttori sintetici ad esso per consentire A per ottenere l'accesso ad esso.

Quando si dà un costruttore B protetta, A può accedere a quel costruttore poiché è nello stesso pacchetto, senza bisogno di un costruttore di sintesi da aggiungere.

Altri suggerimenti

So che questa domanda è vecchia di quasi tre anni, ma trovo che a una parte della domanda non sia ancora stata data risposta:

E:significa che la classe B non è più privata in fase di esecuzione?

Il commento di Carlos Heuberger sulla risposta di skaffman suggerisce, classe B è ancora private per le altre classi del pacchetto.

Probabilmente ha ragione per il linguaggio di programmazione Java, ad es.non è possibile fare riferimento alla classe B da un'altra classe.Almeno non senza l'utilizzo della riflessione (con la quale è possibile accedere dall'esterno anche ai membri privati ​​della classe), ma questa è un'altra questione.

Ma poiché la JVM non ha alcun concetto di classe interna (come afferma skaffman), mi sono chiesto come si realizzi una visibilità "accessibile da una sola classe" a livello di bytecode.La risposta:Non è affatto realizzato, per la JVM la classe interna sembra una normale classe privata del pacchetto.Questo è, se scrivi bytecode per te stesso (o ne modifichi uno generato dal compilatore) puoi accedere a class B senza problemi.

Puoi anche accedere a tutti i metodi di accesso sintetici da tutte le classi nello stesso pacchetto.Quindi, se assegni un valore a un campo privato di class A in un metodo di classe B, un metodo di accesso sintetico con impostazione predefinita (ovveropacchetto privato) la visibilità viene generata in classe A (chiamato qualcosa come access$000) che imposta il valore per te.Questo metodo dovrebbe essere chiamato solo dalla classe B (e in effetti può essere chiamato solo da lì usando il linguaggio Java).Ma dal punto di vista della JVM, questo è semplicemente un metodo come gli altri e può essere chiamato da qualsiasi classe.

Quindi, per rispondere alla domanda:

  • Dal punto di vista dei linguaggi Java, class B è e rimane privato.
  • Dal punto di vista delle JVM, class B (o meglio:classe A$B) non è privato.

L'accesso di class B e il suo costruttore non devono essere lo stesso. Si può avere una classe interna privata con un costruttore pacchetto-scope, e questo è quello che faccio di solito.

public class A {
  public A() { b = new B(); }
  B b;
  private class B {
    B() { }
  }
}

È necessario utilizzare

this.new B();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top