2013-05-21 4 views

Antwort

21

Java verhindert die Unterklassierung von Klassen mit privaten Konstruktoren nicht.

public class Main { 
    static class A { 
     private A() { 
      System.out.println("Subclassed A in "+getClass().getName()); 
     } 
    } 

    static class B extends A { 
     public B() { 

     } 
    } 

    public static void main(String... ignored) { 
     new B(); 
    } 
} 

druckt

Subclassed A in Main$B 

Was es verhindert ist Unterklassen, die keine Konstrukteure seiner Superklasse zugreifen können. Dies bedeutet, dass ein privater Konstruktor nicht in einer anderen Klassendatei verwendet werden kann und ein lokaler Konstruktor eines Pakets nicht in einem anderen Paket verwendet werden kann.

In dieser Situation ist die einzige Option, die Sie haben, Delegation. Sie müssen eine Factory-Methode aufrufen, um eine Instanz der Klasse "super" zu erstellen und sie zu umbrechen.

+0

etwas ist nicht richtig? eine verschachtelte statische Klasse instanziieren? wie funktioniert es? – Jaxox

+0

@jaxox zum jvm, verschachtelte Klassen sind nichts besonderes. Sie sind wie jede andere Klasse mit einer aber mehr Meta-Informationen. Sie können also eine Klasse erstellen, die auf die gleiche Weise wie jede andere verschachtelt definiert wurde. Btw anonyme Klassen in statischen Methoden sind auch static geschachtelte Klassen. –

+0

@PeterLawrey Ich verstehe, was Sie sagen, aber ich bin immer noch leicht verwirrt. Haben Sie nicht gesagt, dass Java es Unterklassen nicht erlaubt, auf entsprechende Superklassenkonstruktoren zuzugreifen? In Ihrem Beispiel hat Klasse B keinen Zugriff auf den Konstruktor von A. Wie ist das erlaubt? – Grateful

18

Da eine Klasse mussimmer seine Superklasse Konstruktor aufrufen. Wenn auf den Superklassenkonstruktor nicht zugegriffen werden kann, kann die Unterklasse nicht initialisiert werden.

Weitere Informationen: JLS 8.8.10. Preventing Instantiation of a Class


In Bezug auf Brian Roach Kommentare:

Der Aufruf [zu dem übergeordneten Klasse Konstruktor] ist nur implizit, wenn Sie es nicht tun, explizit und die Eltern haben ein öffentlicher oder geschützter Nicht-Arg-Konstruktor (oder hat keinen definiert, in welchem ​​Fall es einen Standard-Nicht-Arg gibt). Es ist erforderlich, weil ... so funktioniert die Sprache. Kinder [Klassen] müssen [ihren] Elternkonstruktor aufrufen.

Beachten Sie, dass, wenn Sie jede Klasse in Java instanziiert, gibt es immer einen impliziten Aufruf von Object Konstruktor, da es die Superklasse aller Klassen ist.

public Object() { 
} 

Vermerk des JLS Link: Sie wird ihre default constructor ausführen

Es ist ein Fehler bei der Kompilierung, wenn ein Standard-Konstruktor implizit deklariert, aber die übergeordnete Klasse nicht über einen zugänglichen Konstruktor (§6.6) das keine Argumente annimmt und keine throws-Klausel hat.

+0

Und warum ist das eine notwendige Bedingung, auch wenn sie implizit ist? – CodeBlue

+1

Wenn die Elternklasse einen privaten Konstruktor deklariert hat, ist nichts implizit. Es würde einen expliziten Aufruf im Child erfordern, aber da der Konstruktor privat ist, können Sie nicht. –

+0

Es gibt einen impliziten Aufruf von super() in jedem Konstruktor, sofern Sie nicht selbst einen angeben. – cogsmos

1

Wenn der Konstruktor einer Klasse privat ist, kann die untergeordnete Klasse keinen Aufruf an den Superkonstruktor vornehmen. Daher würde die Vererbung fehlschlagen.

0

Ja, etwas zu Luiggi Antwort diese Funktion von Java-Zugabe verwendet wird, wenn die Singleton-Klassen zu schaffen, das nur eine Instanz dieser Klasse erlaubt geschaffen werden.

+1

Nicht, wenn Sie ein Singleton korrekt erstellen. –

+0

@Brian können Sie mir bitte sagen, wie man es richtig macht, ohne den Konstruktor privat zu machen? –

+2

Josh Bloch, 'Effektive Java zweite Ausgabe' - verwenden Sie eine 'enum'. Siehe: http://stackoverflow.com/questions/5759596/the-best-singleton-pattern-since-java-5. Wenn Sie dieses Buch nicht haben, kaufen Sie es. Es ist ein Muss für jeden, der ernsthaft über Java ist –

1

Wenn Sie eine Unterklasse haben, haben Sie 2 Möglichkeiten für Kindklasse (Unterklasse): 1. Standardkonstruktor (Kein Argumentkonstruktor): In diesem Fall versucht der Standardkonstruktor automatisch, den Elternklassenkonstruktor aufzurufen: this will fehlgeschlagen, da der Elternklassenkonstruktor privat ist. 2.Parametrisierter Konstruktor: Wenn Sie versuchen, ein Objekt für eine Kindklasse zu erstellen, die den Konstruktor parametrisiert hat, müssen Sie den Elternklassenkonstruktor zwingend vom Kindklassenkonstruktor aus aufrufen, indem Sie Parameter übergeben oder Parameter nicht übergeben: Dies wird auch fehlschlagen, da der Elternkonstruktor privat ist.

Da die untergeordnete Klasse entweder einen Standardkonstruktor oder einen parametrisierten Konstruktor hat und es nicht möglich ist, einen von beiden zu haben, können Sie keine Unterklasse für eine Elternklasse mit privatem Konstruktor haben.

Verwandte Themen