Nehmen wir an, ich habe eine Basisklasse namens Entity
. In dieser Klasse habe ich eine statische Methode, um den Klassennamen abzurufen:
class Entity {
public static String getClass() {
return Entity.class.getClass();
}
}
Jetzt habe ich eine andere Klasse, die das erweitert.
class User extends Entity {
}
Ich möchte den Klassennamen von User erhalten:
System.out.println(User.getClass());
Mein Ziel ist es, die Ausgabe von "com.packagename.User" auf der Konsole anzuzeigen. Stattdessen werde ich mit "com.packagename.Entity" enden, da auf die Entity-Klasse direkt von der statischen Methode verwiesen wird.
Wenn dies keine statische Methode war, konnte dies leicht mit dem Schlüsselwort this
innerhalb der Klasse Entity
(d. H .: return this.class.getClass()
) gelöst werden. Ich brauche diese Methode jedoch, um statisch zu bleiben. Irgendwelche Vorschläge, wie man dies angehen kann?
Nicht möglich. Statische Methoden sind in keiner Weise laufzeitpolymorph. Es ist absolut unmöglich, diese Fälle zu unterscheiden:
System.out.println(Entity.getClass());
System.out.println(User.getClass());
Sie kompilieren zu demselben Bytecode (vorausgesetzt, dass die Methode in Entity
definiert ist).
Wie würden Sie diese Methode auf eine Weise nennen, bei der es sinnvoll wäre, dass sie polymorph ist?
Machen Sie die Methode nicht statisch. Das Problem ist, dass Sie beim Aufruf von getClass()
die Methode in der Superklasse aufrufen - statische Methoden werden nicht geerbt. Darüber hinaus sind Sie im Grunde nur ein Namensschilder Object.getClass()
, was verwirrend ist.
Wenn Sie den Klassennamen in der Superklasse protokollieren müssen, verwenden Sie
return this.getClass().getName();
Dies gibt "Entity" zurück, wenn Sie eine Entity
-Instanz haben, "User", wenn Sie eine User
-Instanz haben, usw.
Ihre Frage ist mehrdeutig, aber soweit ich das beurteilen kann, möchten Sie die aktuelle Klasse von einer statischen Methode erfahren. Die Tatsache, dass Klassen voneinander erben, ist irrelevant, aber im Interesse der Diskussion habe ich sie auch so implementiert.
Klasse Parent { public static void printClass () { System.out.println (Thread.currentThread (). GetStackTrace () [2] .getClassName ()); } } public class Test erweitert Parent { public static void main (String [] args) { printClass (); } }
Das funktioniert für mich
this.getClass().asSubclass(this.getClass())
Aber ich bin nicht sicher, wie es funktioniert.
Die Superklasse sollte nicht einmal die Existenz der Unterklasse kennen, noch weniger Operationen auf der Grundlage des vollständig qualifizierten Namens der Unterklasse ausführen. Wenn Sie Operationen benötigen, die auf der genauen Klasse basieren, und die erforderliche Funktion nicht durch Vererbung ausführen können, sollten Sie Folgendes tun:
public class MyClassUtil
{
public static String doWorkBasedOnClass(Class<?> clazz)
{
if(clazz == MyNormalClass.class)
{
// Stuff with MyNormalClass
// Will not work for subclasses of MyNormalClass
}
if(isSubclassOf(clazz, MyNormalSuperclass.class))
{
// Stuff with MyNormalSuperclass or any subclasses
}
// Similar code for interface implementations
}
private static boolean isSubclassOf(Class<?> subclass, Class<?> superclass)
{
if(subclass == superclass || superclass == Object.class) return true;
while(subclass != superclass && subclass != Object.class)
{
subclass = subclass.getSuperclass();
}
return false;
}
}
(Nicht getesteter Code)
Diese Klasse kennt auch keine eigenen Unterklassen, sondern verwendet stattdessen die Class
-Klasse, um Operationen auszuführen. Höchstwahrscheinlich wird es immer noch eng mit Implementierungen verknüpft sein (im Allgemeinen eine schlechte Sache, oder wenn es nicht schlecht ist, ist es nicht besonders gut ), aber ich denke, eine solche Struktur ist besser als eine Superklasse, die herausfindet, was alles ist Unterklassen sind.
Warum möchten Sie Ihre eigene getClass () -Methode implementieren? Sie können einfach verwenden
System.out.println(User.class);
Bearbeiten (um etwas zu erarbeiten): Die Methode soll statisch sein. In diesem Fall müssen Sie die Methode für die Klasse aufrufen, deren Klassenname Sie wünschen, sei es die Unterklasse oder die Oberklasse. Anstatt MyClass.getClass()
aufzurufen, können Sie einfach MyClass.class
oder MyClass.class.getName()
aufrufen.
Außerdem erstellen Sie eine static
-Methode mit derselben Signatur wie die Object.getClass()
-Instanzmethode, die nicht kompiliert werden kann.
Jedes Mal, wenn die erweiterte Klasse instanziiert wird, wird ihr Name im String gespeichert und kann mit dem Getter abgerufen werden.
Mein Kontext: Oberklasse Entität mit Unterklassen für XML-Objekte . Meine Lösung: Erstellen Sie eine Klassenvariable in der Oberklasse
Class<?> claz;
Dann würde ich in der Unterklasse die Variable der Oberklasse im Konstruktor setzen
public class SubClass {
public SubClass() {
claz = this.getClass();
}
}
Eine statische Methode ist einer Klasse zugeordnet, nicht einem bestimmten Objekt.
Berücksichtigen Sie, wie dies funktionieren würde, wenn mehrere Unterklassen vorhanden wären. Der Administrator ist beispielsweise auch eine Entität. Wie würde Ihre statische Entity-Methode, die nur der Entity-Klasse zugeordnet ist, wissen, welche Unterklasse Sie wünschen?
Du könntest:
Wenn ich Ihre Frage richtig verstehe, glaube ich, dass Sie die einzige Möglichkeit erreichen können, die statische Methode in jeder Unterklasse neu zu implementieren, zum Beispiel:
class Entity {
public static String getMyClass() {
return Entity.class.getName();
}
}
class Derived extends Entity {
public static String getMyClass() {
return Derived.class.getName();
}
}
Dadurch wird package.Entity und package.Derived wie gewünscht gedruckt. Chaotisch aber hey, wenn das deine Zwänge sind ...
Wenn ich es richtig mache, möchten Sie Ihre Unterklasse in der Basisklasse in der statischen Methode .__ verwenden. Ich denke, Sie können dies tun, indem Sie der Methode einen Klassenparameter übergeben
class Entity {
public static void useClass(Class c) {
System.out.println(c);
// to do code here
}
}
class User extends Entity {
}
class main{
public static void main(String[] args){
Entity.useClass(Entity.class);
}
}