Java - den aktuellen Klassennamen erhalten?

271

Ich versuche nur, den aktuellen Klassennamen abzurufen, und Java hängt eine nutzlose, unsinnige $ 1 an das Ende meines Klassennamens an. Wie kann ich es loswerden und nur den tatsächlichen Klassennamen zurückgeben?

String className = this.getClass().getName();
aryaxt
quelle
1
Wo nennst du das? Ist es aus einer anonymen inneren Klasse? Könnten Sie weiteren Code hinzufügen, der Details zur Definition der Klasse und zu dem Ort enthält, von dem aus diese Zeile aufgerufen wird?
Plainjimbo
8
Also, alles was Sie wollen istString className = getClass().getName().substring(0, getClass().getName().indexOf("$"))
josh.trow
9
Wenn Sie $1dann bekommen , weil der Name der Klasse ist $1. Wenn Sie etwas anderes erwarten, verwenden Sie thisin der richtigen Klasse anstelle der falschen.
Ceving

Antworten:

247

Das "$ 1" ist nicht "nutzlos unsinnig". Wenn Ihre Klasse anonym ist, wird eine Nummer angehängt.

Wenn Sie die Klasse selbst nicht möchten, sondern ihre deklarierende Klasse, können Sie sie verwenden getEnclosingClass(). Zum Beispiel:

Class<?> enclosingClass = getClass().getEnclosingClass();
if (enclosingClass != null) {
  System.out.println(enclosingClass.getName());
} else {
  System.out.println(getClass().getName());
}

Sie können dies in einer statischen Dienstprogrammmethode verschieben.

Beachten Sie jedoch, dass dies nicht der aktuelle Klassenname ist. Die anonyme Klasse unterscheidet sich von der umschließenden Klasse. Ähnlich verhält es sich mit inneren Klassen.

Bozho
quelle
2
Was aber, wenn die einschließende Klasse auch eine anonyme innere Klasse ist? Müssen Sie die einschließende Klasse nicht rekursiv abrufen, bis sie zurückkehrt null, und die letzte Nichtklasse verwenden null, die Sie erhalten haben?
Garret Wilson
231

Versuchen,

String className = this.getClass().getSimpleName();

Dies funktioniert so lange, wie Sie es nicht in einer statischen Methode verwenden.

jesg
quelle
1
Nein, das wird nicht funktionieren. Diese Frage zeigt an, dass er eine anonyme innere Klasse hat, und für diesen Fall gibt getSimpleName () zurück""
vikingsteve
48
Auch wenn dies die Frage nicht beantwortet, befindet sich dieser SO-Beitrag derzeit in den Top-Ergebnissen für "get class name java" bei Google und ist daher für die Community weiterhin hilfreich.
EdgeCaseBerg
6
Es wird ein Name ohne Paket-Namespace zurückgegeben. Gut!
Oleg Abrazhaev
31

Versuchen Sie dies this.getClass().getCanonicalName()oder this.getClass().getSimpleName(). Wenn es sich um eine anonyme Klasse handelt, verwenden Siethis.getClass().getSuperclass().getName()

MirroredFate
quelle
Eigentlich schon. Abhängig. Wenn Sie versuchen, den Namen der abstrakten Klasse zu ermitteln, die Sie mit einer anonymen Klasse implementieren, verwenden Sie diese.
MirroredFate
Für seinen Fall (anonyme Klasse) ist der einfache Name leer, der kanonische Name ist null und die Oberklasse ist Object.
Bozho
Ja, ja, nein. Meine ersten beiden waren nur Vermutungen, die dritte ist jedoch richtig. Eine anonyme Klasse ist eine Unterklasse der Klasse, die sie implementiert. Deshalb arbeiten sie. Die Oberklasse ist also die abstrakte Klasse.
MirroredFate
Seltsam, ist die Superklasse nicht die Klasse, von der Sie erben? Handler
erbt
Umm ... Ich habe das getestet und ich verstehe, dass die Oberklasse der anonymen Klasse die abstrakte Klasse ist. Ich werde meine Logik noch einmal überprüfen ... aber da ich das Ergebnis erhalte, das Sinn macht, glaube ich nicht, dass ich den Fehler gemacht habe ...
MirroredFate
10

Sie können this.getClass().getSimpleName()wie folgt verwenden:

import java.lang.reflect.Field;

public class Test {

    int x;
    int y;  

    public void getClassName() {
        String className = this.getClass().getSimpleName(); 
        System.out.println("Name:" + className);
    }

    public void getAttributes() {
        Field[] attributes = this.getClass().getDeclaredFields();   
        for(int i = 0; i < attributes.length; i++) {
            System.out.println("Declared Fields" + attributes[i]);    
        }
    }

    public static void main(String args[]) {

        Test t = new Test();
        t.getClassName();
        t.getAttributes();
    }
}
Karuna
quelle
4

Die Kombination beider Antworten. Gibt auch einen Methodennamen aus:

Class thisClass = new Object(){}.getClass();
String className = thisClass.getEnclosingClass().getSimpleName();
String methodName = thisClass.getEnclosingMethod().getName();
Log.d("app", className + ":" + methodName);
SoftDesigner
quelle
3

Diese Antwort ist spät, aber ich denke, es gibt einen anderen Weg, dies im Kontext einer anonymen Handler-Klasse zu tun.

sagen wir:

class A {
    void foo() {
        obj.addHandler(new Handler() {
            void bar() {
                String className=A.this.getClass().getName();
                // ...
            }
        });
    }
}

es wird das gleiche Ergebnis erzielen. Darüber hinaus ist es praktisch, da jede Klasse zur Kompilierungszeit definiert wird, sodass keine Dynamik beeinträchtigt wird.

darüber hinaus, wenn die Klasse wirklich verschachtelt ist, dh AB die Klasse von B leicht bekannt sein tatsächlich eingeschlossen ist durch :

B.this.getClass().getName()
Jason Hu
quelle
2

In Ihrem Beispiel thisbezieht sich wahrscheinlich auf eine anonyme Klasseninstanz. Java gibt diesen Klassen einen Namen, indem a $numberan den Namen der einschließenden Klasse angehängt wird.

Tonio
quelle
2
Nicht anonyme innere Klassen heißen Outer $ Inner. Dies wird eine anonyme Klasse sein.
Duncan McGregor
1

Ich gehe davon aus, dass dies für eine anonyme Klasse geschieht. Wenn Sie eine anonyme Klasse erstellen, erstellen Sie tatsächlich eine Klasse, die die Klasse erweitert, deren Namen Sie erhalten haben.

Der "sauberere" Weg, um den gewünschten Namen zu erhalten, ist:

Wenn Ihre Klasse eine anonyme innere Klasse ist, getSuperClass()sollten Sie die Klasse angeben, aus der sie erstellt wurde. Wenn Sie es über eine Schnittstelle erstellt haben, sind Sie eine Art SOL, denn das Beste, was Sie tun können, ist getInterfaces(), dass Sie möglicherweise mehr als eine Schnittstelle erhalten.

Der "hackige" Weg ist, einfach den Namen mit zu bekommen getClassName()und einen regulären Ausdruck zu verwenden, um das zu löschen $1.

Wahrhaftigkeit
quelle
0

Hier ist eine Android-Variante, aber das gleiche Prinzip kann auch in einfachem Java verwendet werden.

private static final String TAG = YourClass.class.getSimpleName();
private static final String TAG = YourClass.class.getName();
Ako
quelle
-3

Ich habe festgestellt, dass dies für meinen Code funktioniert, aber mein Code holt die Klasse aus einem Array innerhalb einer for-Schleife heraus.

String className="";

className = list[i].getClass().getCanonicalName();

System.out.print(className); //Use this to test it works
hransom
quelle
Dies fügt nichts hinzu, was keine der anderen Antworten bereits gesagt hat. Das gesamte Loop / Array-Problem ist irrelevant. Außerdem sollten Sie untersuchen, wie die Code-Formatierung bei Fragen / Antworten funktioniert.
Jonathon Reinhart
-4

Reflexions-APIs

Es gibt mehrere Reflection-APIs, die Klassen zurückgeben. Auf diese kann jedoch nur zugegriffen werden, wenn eine Klasse bereits direkt oder indirekt abgerufen wurde.

Class.getSuperclass()
     Returns the super class for the given class.

        Class c = javax.swing.JButton.class.getSuperclass();
        The super class of javax.swing.JButton is javax.swing.AbstractButton.

        Class.getClasses()

Gibt alle öffentlichen Klassen, Schnittstellen und Aufzählungen zurück, die Mitglieder der Klasse sind, einschließlich geerbter Mitglieder.

        Class<?>[] c = Character.class.getClasses();

Character enthält zwei Mitgliedsklassen Character.Subset und
Character.UnicodeBlock.

        Class.getDeclaredClasses()
         Returns all of the classes interfaces, and enums that are explicitly declared in this class.

        Class<?>[] c = Character.class.getDeclaredClasses();
     Character contains two public member classes Character.Subset and Character.UnicodeBlock and one private class

Character.CharacterCache.

        Class.getDeclaringClass()
        java.lang.reflect.Field.getDeclaringClass()
        java.lang.reflect.Method.getDeclaringClass()
        java.lang.reflect.Constructor.getDeclaringClass()
     Returns the Class in which these members were declared. Anonymous Class Declarations will not have a declaring class but will

eine einschließende Klasse haben.

        import java.lang.reflect.Field;

            Field f = System.class.getField("out");
            Class c = f.getDeclaringClass();
            The field out is declared in System.
            public class MyClass {
                static Object o = new Object() {
                    public void m() {} 
                };
                static Class<c> = o.getClass().getEnclosingClass();
            }

     The declaring class of the anonymous class defined by o is null.

    Class.getEnclosingClass()
     Returns the immediately enclosing class of the class.

    Class c = Thread.State.class().getEnclosingClass();
     The enclosing class of the enum Thread.State is Thread.

    public class MyClass {
        static Object o = new Object() { 
            public void m() {} 
        };
        static Class<c> = o.getClass().getEnclosingClass();
    }
     The anonymous class defined by o is enclosed by MyClass.
Arunkumar Sambu
quelle
2
Ist Ihnen bekannt, dass Sie Ihre Antwort als monolithischen Codeblock veröffentlicht haben? Die Anweisungen sollten nicht als Code-Anführungszeichen formatiert werden ...
Massimiliano Kraus