Während eines meiner Interviews wurde ich gefragt: "Können wir eine abstrakte Klasse instanziieren?"
Meine Antwort war "Nein, wir können nicht". Aber der Interviewer sagte mir: "Falsch, wir können."
Ich habe ein bisschen darüber gestritten. Dann sagte er mir, ich solle es selbst zu Hause versuchen.
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
Hier erstelle ich eine Instanz meiner Klasse und rufe die Methode der abstrakten Klasse auf. Kann mir bitte jemand das erklären? Habe ich mich während meines Interviews wirklich geirrt?
B
von einer abstrakten einA
, während der Teil der Konstruktion vonB
Beispiel , die aus laufendenA
‚s Konstruktor, der Laufzeittyp des Objekts ist tatsächlichA
. Nur vorübergehend.Antworten:
Nein, Sie erstellen hier nicht die Instanz Ihrer abstrakten Klasse. Sie erstellen vielmehr eine Instanz einer anonymen Unterklasse Ihrer abstrakten Klasse. Anschließend rufen Sie die Methode für Ihre abstrakte Klassenreferenz auf, die auf ein Unterklassenobjekt verweist .
Dieses Verhalten ist in JLS - Abschnitt 15.9.1 klar aufgeführt : -
Hervorhebung von mir.
In JLS - Abschnitt 12.5 können Sie außerdem Informationen zum Objekterstellungsprozess lesen . Ich werde hier eine Aussage daraus zitieren:
Den vollständigen Vorgang finden Sie unter dem von mir angegebenen Link.
Um praktisch zu sehen, dass die zu instanziierende Klasse eine anonyme Unterklasse ist , müssen Sie nur beide Klassen kompilieren. Angenommen, Sie legen diese Klassen in zwei verschiedenen Dateien ab:
My.java:
Poly.java:
Kompilieren Sie nun beide Quelldateien:
In dem Verzeichnis, in dem Sie den Quellcode kompiliert haben, werden die folgenden Klassendateien angezeigt:
Siehe diese Klasse -
Poly$1.class
. Dies ist die vom Compiler erstellte Klassendatei, die der anonymen Unterklasse entspricht, die Sie mit dem folgenden Code instanziiert haben:Es ist also klar, dass eine andere Klasse instanziiert wird. Es ist nur so, dass diese Klasse erst nach der Kompilierung durch den Compiler einen Namen erhält.
Im Allgemeinen werden alle anonymen Unterklassen in Ihrer Klasse folgendermaßen benannt:
Diese Zahlen bezeichnen die Reihenfolge, in der diese anonymen Klassen in der umschließenden Klasse erscheinen.
quelle
instance of
und gibtinstantiating
. Sie instanziieren nur eine Klasse, während das von Ihnen erstellte Objekt aufgrund der Vererbung eine Instanz mehrerer Klassen sein kann.Das Obige instanziiert eine anonyme innere Klasse, die eine Unterklasse der
my
abstrakten Klasse ist. Es ist nicht unbedingt gleichbedeutend mit der Instanziierung der abstrakten Klasse selbst. OTOH, jede Unterklasseninstanz ist eine Instanz aller ihrer Superklassen und Schnittstellen, sodass die meisten abstrakten Klassen tatsächlich durch Instanziieren einer ihrer konkreten Unterklassen instanziiert werden.Wenn der Interviewer nur "falsch" sagte! Ohne es zu erklären und dieses Beispiel als einzigartiges Gegenbeispiel zu nennen, denke ich, dass er nicht weiß, wovon er spricht.
quelle
subclassInstance instanceof SuperClass
würde true zurückgeben, daher ist das Objekt eine Instanz der Oberklasse, was bedeutet, dass die Oberklasse instanziiert wurde. Aber das ist nur semantisches Nitpicking.= my() {};
bedeutet, dass es eine anonyme Implementierung gibt, nicht eine einfache Instanziierung eines Objekts, die hätte sein sollen := my()
. Sie können niemals eine abstrakte Klasse instanziieren.quelle
Nur Beobachtungen, die Sie machen könnten:
poly
verlängertmy
? Das ist nutzlos ...my.class
,poly.class
undpoly$1.class
Können wir eine abstrakte Klasse instanziieren?
Nein, wir können nicht. Wir können eine anonyme Klasse erstellen (das ist die dritte Datei) und sie instanziieren.
Was ist mit einer erstklassigen Instanziierung?
Die abstrakte Superklasse wird nicht von uns, sondern von Java instanziiert .
EDIT: Bitten Sie ihn, dies zu testen
Ausgabe ist:
quelle
Serializable s = new Serializable() {};
(was ziemlich nutzlos ist) und wenn auf Ihrem Code markiert würdeclass my$3
(oder was auch immer Klasse und Nummer einschließt)Sie können einfach in nur einer Zeile antworten
Aber, Interviewer immer noch nicht einverstanden, dann können Sie ihm / ihr sagen
Und gemäß der anonymen Klasse wird die Klasse an derselben Stelle / Zeile deklariert und instanziiert
Es ist also möglich, dass der Interviewer daran interessiert ist, Ihr Konfidenzniveau und Ihr Wissen über die OOPs zu überprüfen.
quelle
Der technische Teil wurde in den anderen Antworten ausführlich behandelt und endet hauptsächlich mit:
"Er liegt falsch, er weiß nichts, bitte ihn, sich SO anzuschließen und alles zu klären :)"
Ich möchte auf die Tatsache eingehen (die in anderen Antworten erwähnt wurde), dass dies eine Stressfrage sein könnte und für viele Interviewer ein wichtiges Instrument ist, um mehr über Sie zu erfahren und wie Sie auf schwierige und ungewöhnliche Situationen reagieren. Indem er Ihnen falsche Codes gab, wollte er wahrscheinlich sehen, ob Sie zurückgestritten haben. Zu wissen, ob Sie das Vertrauen haben, sich in ähnlichen Situationen gegen Ihre Senioren zu behaupten.
PS: Ich weiß nicht warum, aber ich habe das Gefühl, dass der Interviewer diesen Beitrag gelesen hat.
quelle
Abstrakte Klassen können nicht instanziiert, aber in Unterklassen unterteilt werden. Siehe diesen Link
Das beste Beispiel ist
Zwar hat die Kalenderklasse eine abstrakte Methode getInstance () , aber wenn Sie sagen
Calendar calc=Calendar.getInstance();
calc bezieht sich auf die Klasseninstanz der Klasse GregorianCalendar als "GregorianCalendar erweitert Kalender "
Mit dem anonymen inneren Typ von Infact können Sie eine No-Name-Unterklasse der abstrakten Klasse und eine Instanz davon erstellen .
quelle
Technische Antwort
Abstrakte Klassen können nicht instanziiert werden - dies ist per Definition und Design.
Aus dem JLS, Kapitel 8. Klassen:
Aus JSE 6 Java Doc für Classes.newInstance ():
Sie können natürlich eine konkrete Unterklasse einer abstrakten Klasse (einschließlich einer anonymen Unterklasse) instanziieren und auch eine Typumwandlung eines Objektverweises auf einen abstrakten Typ durchführen.
Ein anderer Blickwinkel - Teamplay & Social Intelligence:
Diese Art von technischem Missverständnis tritt in der realen Welt häufig auf, wenn wir uns mit komplexen Technologien und legalistischen Spezifikationen befassen.
"People Skills" können hier wichtiger sein als "Technical Skills". Wenn Sie wettbewerbsfähig und aggressiv versuchen, Ihre Seite des Arguments zu beweisen, könnten Sie theoretisch Recht haben, aber Sie könnten auch mehr Schaden anrichten, wenn Sie einen Kampf führen / ein "Gesicht" beschädigen / einen Feind erschaffen, als es wert ist. Seien Sie versöhnlich und verständnisvoll bei der Lösung Ihrer Differenzen. Wer weiß - vielleicht haben Sie "beide Recht", arbeiten aber etwas andere Bedeutungen für Begriffe aus?
Wer weiß - obwohl nicht wahrscheinlich, ist es möglich, dass der Interviewer absichtlich einen kleinen Konflikt / ein Missverständnis eingeführt hat, um Sie in eine herausfordernde Situation zu bringen und zu sehen, wie Sie sich emotional und sozial verhalten. Seien Sie freundlich und konstruktiv gegenüber Kollegen, befolgen Sie die Ratschläge von Senioren und setzen Sie sich nach dem Interview durch, um alle Herausforderungen / Missverständnisse zu lösen - per E-Mail oder Telefonanruf. Zeigt, dass Sie motiviert und detailorientiert sind.
quelle
Es ist eine allgemein anerkannte Tatsache,
abstract class
die nicht instanziiert werden kann, wenn alle geantwortet haben.Wenn das Programm eine anonyme Klasse definiert, erstellt der Compiler tatsächlich eine neue Klasse mit einem anderen Namen (hat das Muster,
EnclosedClassName$n
in demn
sich die anonyme Klassennummer befindet).Wenn Sie diese Java-Klasse dekompilieren, finden Sie den folgenden Code:
meine Klasse
poly $ 1.class (die generierte Klasse der "anonymen Klasse")
ploly.cass
quelle
Nein, Sie können eine abstrakte Klasse nicht instanziieren. Wir instanziieren nur eine anonyme Klasse. In einer abstrakten Klasse deklarieren wir abstrakte Methoden und definieren nur konkrete Methoden.
quelle
Über abstrakte Klassen
Der Zweck einer abstrakten Klasse besteht darin, sich wie eine Basis zu verhalten. In der Vererbungshierarchie sehen Sie abstrakte Klassen nach oben.
quelle
Sie können sagen:
Wir können eine abstrakte Klasse nicht instanziieren, aber wir können ein
new
Schlüsselwort verwenden, um eine anonyme Klasseninstanz zu erstellen, indem wir{}
am Ende der abstrakten Klasse nur als Implementierungskörper hinzufügen .quelle
Das Erweitern einer Klasse bedeutet nicht, dass Sie die Klasse instanziieren. In Ihrem Fall erstellen Sie tatsächlich eine Instanz der Unterklasse.
Ich bin mir ziemlich sicher, dass abstrakte Klassen keine Initiierung erlauben. Also würde ich nein sagen: Sie können eine abstrakte Klasse nicht instanziieren. Aber Sie können es erweitern / erben.
Sie können eine abstrakte Klasse nicht direkt instanziieren. Dies bedeutet jedoch nicht, dass Sie eine Instanz der Klasse (nicht wirklich eine Instanz der ursprünglichen abstrakten Klasse) indirekt erhalten können. Ich meine, Sie können die ursprüngliche abstrakte Klasse nicht instanziieren, aber Sie können:
So erhalten Sie über die abgeleitete Klasseninstanz Zugriff auf alle Methoden und Eigenschaften einer abstrakten Klasse.
quelle
Es ist unmöglich, eine abstrakte Klasse zu instanziieren. Was Sie wirklich tun können, ist, einige gängige Methoden in einer abstrakten Klasse zu implementieren und andere nicht implementieren zu lassen (sie als abstrakt zu deklarieren) und sie vom konkreten Absteiger je nach ihren Anforderungen implementieren zu lassen. Dann können Sie eine Factory erstellen, die eine Instanz dieser abstrakten Klasse (tatsächlich seinen Implementierer) zurückgibt. In der Fabrik entscheiden Sie dann, welchen Implementierer Sie wählen möchten. Dies ist als Werksentwurfsmuster bekannt:
Der konkrete Implementierer muss nur die als abstrakt deklarierten Methoden implementieren, hat jedoch Zugriff auf die Logik, die in den Klassen einer abstrakten Klasse implementiert ist, die nicht als abstrakt deklariert sind:
Dann sieht die Fabrik endlich so aus:
Der Empfänger von AbstractGridManager würde die Methoden für ihn aufrufen und die Logik abrufen, die im konkreten Abstieg (und teilweise in den abstrakten Klassenmethoden) implementiert ist, ohne zu wissen, welche konkrete Implementierung er erhalten hat. Dies wird auch als Inversion der Kontrolle oder Abhängigkeitsinjektion bezeichnet.
quelle
Nein, wir können das Objekt der abstrakten Klasse nicht erstellen, sondern die Referenzvariable der abstrakten Klasse. Die Referenzvariable wird verwendet, um auf die Objekte abgeleiteter Klassen (Unterklassen der abstrakten Klasse) zu verweisen.
Hier ist das Beispiel, das dieses Konzept veranschaulicht
Hier sehen wir, dass wir das Objekt vom Typ Figure nicht erstellen können, aber wir können eine Referenzvariable vom Typ Figure erstellen. Hier haben wir eine Referenzvariable vom Typ Figure erstellt. Die Referenzvariable der Klasse Class wird verwendet, um auf die Objekte der Klassen Rectangle und Triangle zu verweisen.
quelle
Eigentlich können wir ein Objekt einer abstrakten Klasse nicht direkt erstellen. Was wir erstellen, ist eine Referenzvariable eines abstrakten Aufrufs. Die Referenzvariable wird verwendet, um auf das Objekt der Klasse zu verweisen, die die abstrakte Klasse erbt, dh die Unterklasse der abstrakten Klasse.
quelle