2015-01-21 4 views
5

Nehmen wir an, wir haben eine Klasse:Anonym Initialisierung der Klasse mit geschützten Konstruktor

public class SomeClass {  
    protected SomeClass() { 
    } 
} 

In MainClass in verschiedenen Paket befindet ich versucht, zwei Zeilen auszuführen:

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

Wegen protected Konstruktor in In beiden Fällen erwartete ich, dass das Programm fehlschlägt. Zu meiner Überraschung funktionierte die anonyme Initialisierung gut. Könnte mir jemand erklären, warum die zweite Methode der Initialisierung in Ordnung ist?

Antwort

8

Ihre anonyme Klasse

SomeClass sac2 = new SomeClass() {}; 

wird im Grunde

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

Der Konstruktor keinen Zugriffsmodifikator hat, so dass Sie es problemlos aus dem gleichen Paket aufrufen kann. Sie können auch super() aufrufen, da der übergeordnete Konstruktor protected über einen Unterklassenkonstruktor zugreifbar ist.

+0

Zu meiner großen Überraschung passiert das Gleiche, wenn Sie einen Konstruktor verwenden, der Argumente hat. In diesem Fall denke ich, dass deine Erklärung nicht länger steht. – Andrei

+0

@Andrei Ich habe Parameter/Argumente nicht erwähnt. Sie spielen keine Rolle bei der Barrierefreiheitsprüfung. –

+0

Nicht in der Zugänglichkeitsprüfung, nein. Wenn Sie jedoch eine Klasse mit nur einem geschützten Konstruktor WITH params haben, müssen Sie ihren Konstruktor explizit mit params vom Kind aufrufen. Ich habe gesagt, dass diese Regel für anonyme Klassen übersprungen wird. – Andrei

3

Die erste Zeile fehlschlägt, weil SomeClass ‚s Konstruktor ist protected und MainClass ist nicht in SomeClass‘ s-Paket, und es ist Subklassen nicht MainClass.

Die zweite Zeile ist erfolgreich, da sie eine anonyme Unterklasse von SomeClass erstellt. Diese anonyme innere Klassenunterklasse SomeClass, so hat es Zugriff auf SomeClass 's protected Konstruktor. Der Standardkonstruktor für diese anonyme innere Klasse ruft implizit diesen Superklassenkonstruktor auf.

0

Ihre Linie

SomeClass sac2 = new SomeClass() {}; 

erstellt eine Instanz einer neuen Klasse, die SomeClass erstreckt. Da SomeClass einen geschützten Konstruktor ohne Argumente definiert, kann eine Kindklasse dies implizit in einem eigenen Konstruktor aufrufen, der in dieser Zeile stattfindet.

2

Diese zwei kleinen Klammern in

SomeClass sac2 = new SomeClass() {}; 

viele automatischen Verhalten in Java aufrufen. Folgendes passiert, wenn diese Zeile ausgeführt wird:

  1. Eine anonyme Unterklasse von SomeClass wird erstellt.
  2. Diese anonyme Unterklasse erhält einen standardmäßigen Konstruktor ohne Argumente, genau wie jede andere Java-Klasse, die ohne einen Konstruktor ohne Argumente deklariert wird.
  3. Der Standard Konstruktor ohne Argumente mit Sichtbarkeits public
  4. Der Standard Konstruktor ohne Argumente definiert super() definiert ist, zu nennen (die Konstruktoren was immer zuerst tun no-Arg- ist).
  5. Der Befehl new ruft den Konstruktor ohne Argumente dieser anonymen Unterklasse auf und ordnet das Ergebnis sac2 zu.

Die Standard-Konstruktor ohne Argumente in der anonymen Unterklasse von SomeClass Zugriff auf den protected Konstruktor SomeClass hat, weil die anonyme Unterklasse ein Nachkomme von SomeClass ist, so der Aufruf von super() gültig ist. Die new-Anweisung ruft diesen Standard-Konstruktor ohne Argumente auf, der die Sichtbarkeit public hat.