wake-up-neo.net

Den Namen einer Unterklasse aus einer Superklasse abrufen

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?

61
Matt Huggins

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?

39

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.

80
matt b

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 (); 
 } 
} 
6
Gilead

Das funktioniert für mich

this.getClass().asSubclass(this.getClass())

Aber ich bin nicht sicher, wie es funktioniert.

5
sirolf2009

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.

3
Brian S

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.

2
samitgaur
  1. Erstellen Sie eine Member-String-Variable in der Superklasse.
  2. Fügen Sie this.getClass (). GetName () einem Konstruktor hinzu, der den Wert in der Member-String-Variablen speichert.
  3. Erstellen Sie einen Getter, um den Namen zurückzugeben.

Jedes Mal, wenn die erweiterte Klasse instanziiert wird, wird ihr Name im String gespeichert und kann mit dem Getter abgerufen werden.

2
Dawg 'N IT

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();
   }
}
0

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:

  • Verwenden Sie die vorhandene Methode getClass ().
  • Übergeben Sie ein Argument an Ihre statische Methode getClass () und rufen Sie eine Instanzmethode für dieses Objekt auf.
  • Machen Sie Ihre Methode nicht statisch und benennen Sie sie um.
0
Andy Thomas

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 ...

0
brabster

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);
    }
}
0
Dis Honest