Ich habe diesen Code:
%Vor%Ich weiß, es sieht so aus, als sollte es ein enum sein, und das wäre es, aber es muss von Person, einer abstrakten Klasse, übernommen werden.
Mein Problem ist: Wenn ich versuche, auf die Liste der Jungs zuzugreifen, geht es mir gut. Aber ich versuche auf irgendeinen Guy zuzugreifen, ich habe ein Problem: Guy
wird vor Person
geladen. Da Guy
jedoch Person
erbt, wird Person
geladen und versucht, auf TOM
zuzugreifen, aber da Guy
bereits geladen wird, kann der Ladevorgang nicht erneut gestartet werden. Daher haben wir eine Null Referenz. (Und ImmutableList
akzeptiert keine Null, daher erhalten wir eine Ausnahme.)
Ich weiß also warum das passiert, aber ich bin nicht sicher, wie ich es vermeiden kann. Ich könnte die Liste in die Klasse Guy
verschieben, aber ich habe mehr als eine Implementierung von Person
, und ich hätte gerne eine Master-Liste aller Person
s in der Klasse Person
/ p>
Es kommt mir seltsam vor, dass es möglich ist, eine statische innere Klasse zu laden, ohne ihre enthaltene Klasse zu laden, aber ich denke, es macht Sinn. Gibt es eine Möglichkeit, dieses Problem zu lösen?
Sie könnten Ihre unveränderbare Liste in einer separaten Klasse wie People.GUYS
:
Auf diese Weise können Sie die einzelnen Jungs in der Klasse Guy
behalten:
Eine Lösung um der Lösung willen funktioniert das (für einen einzelnen Thread)
%Vor%OPs Design ist von Natur aus rekursiv. Obwohl Java über eine wohldefinierte Initialisierungsprozedur verfügt (die zurückgeht, wenn die Rekursion erkannt wird), hängt das Verhalten davon ab, welche Klasse zuerst initialisiert wird.
Das Problem wird durch die Anforderung, dass die Felder final
sind, verschlechtert, was die Zuweisung stark einschränkt. Andernfalls können wir if(null) assign
an mehreren Stellen versuchen, um das Problem zu lösen.
Die oben beschriebene Lösung verwendet im Wesentlichen eine temporäre Variable, um die final
Einschränkung zu umgehen.
Eine modifizierte Version mit einer Map, die für eine größere Anzahl von Feldern geeignet ist:
%Vor%Mehrfachgewinde
Es ist möglich, dass ein Thread die Person initialisiert, während ein anderer Thread Guy initialisiert. Deadlock ist möglich, und es passiert in der realen Welt. Daher ist dieses Design inhärent fehlerhaft.
Im Allgemeinen besteht bei zwei Klassen (nicht notwendigerweise Eltern-Kind), die während der statischen Initialisierung voneinander abhängig sind, die Gefahr eines Deadlocks.
Die Anwendung kann so etwas durchmachen, indem sie die Initialisierung beim Programmstart sorgfältig startet. Trotzdem ist das ziemlich gefährlich, und es könnte jemanden in Tage des Debuggens der Hölle schicken.
Soll die absolute Klasse Person
abstract verwendet werden (d. h. ist sie bereits Teil des Legacy-Codes)?
Wenn nicht, dann empfehle ich Ihnen, das Design Ihres Datenmodells in eine Guy enum
-Klasse umzuwandeln, die eine Person-Schnittstelle implementiert. Es gibt viele Vorteile gegenüber dem klassenbasierten Design.
Beachten Sie, dass es in diesem Fall keinen Grund gibt, eine List
-Instanz mit den konstanten Referenzen zu definieren, da die enum-API die GUY.values()
-Methode bereitstellt.
Es würde alle Ihre Initialisierungsfehler lösen und trotzdem mehrere Implementierungen von Person
ermöglichen. Der Nachteil ist die Code-Duplizierung. Die Methoden in Person
müssen in jeder enum-Klasse implementiert werden (wenn es jedoch viele Methoden gibt, können Sie immer eine private statische Hilfsklasse erstellen und Methodenaufrufe an sie weiterleiten.)
Tags und Links java classloader static