2015-01-21 19 views
5

Supponiamo di avere una classe:Anonimo inizializzazione della classe con il costruttore protetto

public class SomeClass {  
    protected SomeClass() { 
    } 
} 

In MainClass trova nel pacchetto differente Ho provato ad eseguire due linee:

public static void main(String[] args) { 
    SomeClass sac1 = new SomeClass(); 
    SomeClass sac2 = new SomeClass() {}; 
} 

A causa di protected costruttore, in entrambi i casi mi aspettavo che il programma fallisse. Con mia sorpresa, l'inizializzazione anonima ha funzionato bene. Qualcuno potrebbe spiegarmi perché il secondo metodo di inizializzazione è ok?

risposta

8

La classe anonima

SomeClass sac2 = new SomeClass() {}; 

diventa fondamentalmente

public class Anonymous extends SomeClass { 
    Anonymous() { 
     super(); 
    } 
} 

Il costruttore non ha modificatore di accesso, in modo da poter invocarlo senza problemi all'interno dello stesso pacchetto. È anche possibile richiamare super() perché il costruttore genitore protected è accessibile da un costruttore sottoclasse.

+0

Con mia grande sorpresa, la stessa cosa accade quando si utilizza un costruttore che ha argomenti. In questo caso penso che la tua spiegazione non sia più valida. – Andrei

+0

@Andrei Non ho menzionato parametri/argomenti. Non svolgono alcun ruolo nel controllo dell'accessibilità. –

+0

Non nel controllo dell'accessibilità, no. Ma se hai una classe con solo un costruttore protetto con parametri, devi invocare esplicitamente il suo costruttore con parametri, dal bambino. Stavo dicendo che questa regola sembra essere saltata per le classi anonime. – Andrei

3

La prima linea fallisce, perché SomeClass 's costruttore è protected e MainClass non è in SomeClass' pacchetto s, e non è la sottoclasse MainClass.

La seconda riga ha esito positivo perché sta creando una sottoclasse anonima di SomeClass. Questa classe interna anonima sottoclasse lo SomeClass, quindi ha accesso al costruttore protected. Il costruttore predefinito per questa classe interna anonima chiama implicitamente questo costruttore della superclasse.

0

La linea

SomeClass sac2 = new SomeClass() {}; 

crea un'istanza di una nuova classe che si estende SomeClass. Poiché SomeClass definisce un costruttore protetto senza argomenti, una classe figlio può chiamarlo implicitamente nel proprio costruttore che sta accadendo in questa riga.

2

Quei due piccoli sostegni in

SomeClass sac2 = new SomeClass() {}; 

invocano un sacco di comportamento automatico in Java. Ecco cosa succede quando viene eseguita la riga:

  1. Viene creata una sottoclasse anonima di SomeClass.
  2. Quella sottoclasse anonima è dotata di un costruttore di default senza argomenti, proprio come qualsiasi altra classe Java dichiarata senza un costruttore senza argomenti.
  3. L'impostazione predefinita costruttore senza argomenti è definito con una visibilità public
  4. L'impostazione predefinita non-argomento del costruttore è definito per chiamare super() (che è ciò che i costruttori no-arg fanno sempre prima).
  5. Il comando new chiama il costruttore senza argomenti di questa sottoclasse anonima e assegna il risultato a sac2.

L'impostazione predefinita non-argomento del costruttore nella sottoclasse anonima di SomeClass ha accesso al protected costruttore SomeClass perché la sottoclasse anonima è un discendente di SomeClass, quindi la chiamata al super() è valido. L'istruzione new chiama questo costruttore predefinito senza argomenti, che ha visibilità public.