Java - uzyskać aktualną nazwę klasy?

271

Wszystko, co próbuję zrobić, to uzyskać aktualną nazwę klasy, a java dołącza bezużyteczny nonsens 1 $ na końcu nazwy mojej klasy. Jak mogę się go pozbyć i zwrócić tylko prawdziwą nazwę klasy?

String className = this.getClass().getName();
aryaxt
źródło
1
Gdzie dzwonisz? Czy pochodzi z anonimowej klasy wewnętrznej? Czy możesz dodać więcej kodu, który pokazuje szczegóły dotyczące definicji klasy i skąd ta linia jest wywoływana?
plainjimbo
8
Więc wszystko, czego chcesz, toString className = getClass().getName().substring(0, getClass().getName().indexOf("$"))
josh.trow
9
Jeśli tak $1, bo nazwa klasy to $1. Jeśli oczekujesz czegoś innego, użyj thisodpowiedniej klasy zamiast niewłaściwej.
ceving

Odpowiedzi:

247

„1 $” nie jest „bezużytecznym nonsensem”. Jeśli twoja klasa jest anonimowa, dodawana jest liczba.

Jeśli nie chcesz samej klasy, ale jej klasy deklarującej, możesz użyć getEnclosingClass(). Na przykład:

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

Możesz przenieść to w jakiś statyczny sposób.

Pamiętaj jednak, że nie jest to obecna nazwa klasy. Klasa anonimowa jest inną klasą niż klasa zamykająca. Sprawa jest podobna w przypadku klas wewnętrznych.

Bozho
źródło
2
Ale co jeśli klasa zamykająca jest również anonimową klasą wewnętrzną? Czy nie musisz rekurencyjnie uzyskiwać klasę zamykającą, dopóki ona nie zwróci null, i użyć ostatniej nieklasy, nullktórą dostałeś?
Garret Wilson
231

Próbować,

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

Będzie to działać, dopóki nie użyjesz go w metodzie statycznej.

jesg
źródło
1
W rzeczywistości nie, to nie zadziała. To pytanie wskazuje, że ma anonimową klasę wewnętrzną i w tym przypadku zwraca getSimpleName ()""
vikingsteve
48
Chociaż to nie odpowiada na pytanie, ten post SO jest obecnie w najlepszych wynikach dla „get class name java” w google, więc nadal jest pomocny dla społeczności.
EdgeCaseBerg,
6
Zwróci nazwę bez przestrzeni nazw pakietów. Dobry!
Oleg Abrazhaev
31

Spróbuj użyć tego this.getClass().getCanonicalName()lub this.getClass().getSimpleName(). Jeśli jest to anonimowa klasa, użyjthis.getClass().getSuperclass().getName()

MirroredFate
źródło
Właściwie to robi. W zależności Jeśli próbujesz uzyskać nazwę klasy abstrakcyjnej, którą wdrażasz za pomocą klasy anonimowej, właśnie tego używasz.
MirroredFate
w jego przypadku (klasa anonimowa) prosta nazwa jest pusta, nazwa kanoniczna jest pusta, a nadklasa to Object.
Bozho
Tak, tak, nie. Moje pierwsze dwa to tylko domysły, trzeci jednak jest poprawny. Anonimowa klasa jest podklasą klasy, którą implementuje. Właśnie dlatego działają. Tak więc nadklasa jest klasą abstrakcyjną.
MirroredFate
Dziwne, czy nie jest to super klasa, z której dziedziczysz? Handler nie dziedziczy po mojej klasie, jest tylko członkiem
aryaxt
Umm ... Przetestowałem to i okazało się, że nadklasą klasy anonimowej jest klasa abstrakcyjna. Ponownie sprawdzę moją logikę ... ale kiedy otrzymuję wynik, który ma sens, nie sądzę, że to ja popełniłem błąd ....
MirroredFate
10

Możesz użyć this.getClass().getSimpleName()tak:

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
źródło
4

Połączenie obu odpowiedzi. Drukuje również nazwę metody:

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

ta odpowiedź jest spóźniona, ale myślę, że można to zrobić w kontekście anonimowej klasy programu obsługi.

powiedzmy:

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

osiągnie ten sam wynik. dodatkowo jest to całkiem wygodne, ponieważ każda klasa jest definiowana w czasie kompilacji, więc żadna dynamika nie jest uszkodzona.

powyżej, jeśli klasa jest naprawdę zagnieżdżona, tzn. Afaktycznie jest ujęta przez B, klasę B można łatwo określić jako:

B.this.getClass().getName()
Jason Hu
źródło
2

W twoim przykładzie thisprawdopodobnie odnosi się do anonimowej instancji klasy. Java nadaje nazwę tym klasom, dodając $numberdo nazwy klasy zamykającej.

tonio
źródło
2
Nieanonimowe klasy wewnętrzne są nazywane Zewnętrzne $ Wewnętrzne. To będzie anonimowa klasa.
Duncan McGregor
1

Zakładam, że dzieje się tak w przypadku anonimowej klasy. Kiedy tworzysz anonimową klasę, faktycznie tworzysz klasę, która rozszerza klasę, której imię masz.

„Czystszym” sposobem na uzyskanie pożądanej nazwy jest:

Jeśli twoja klasa jest anonimową klasą wewnętrzną, getSuperClass()powinna dać ci klasę, z której została utworzona. Jeśli utworzyłeś go z interfejsu, jesteś w pewnym sensie SOL, ponieważ najlepsze, co możesz zrobić, togetInterfaces() może dać ci więcej niż jeden interfejs.

„Hacky” polega na tym, aby po prostu uzyskać nazwę getClassName()i użyć wyrażenia regularnego, aby upuścić $1.

prawdziwość
źródło
0

Oto wariant Androida, ale tę samą zasadę można zastosować również w zwykłej Javie.

private static final String TAG = YourClass.class.getSimpleName();
private static final String TAG = YourClass.class.getName();
Ako
źródło
-3

Przekonałem się, że działa to w moim kodzie, jednak mój kod usuwa klasę z tablicy w pętli for.

String className="";

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

System.out.print(className); //Use this to test it works
hransom
źródło
Nie dodaje to niczego, czego żadna inna odpowiedź jeszcze nie powiedziała. Cała kwestia pętli / tablicy nie ma znaczenia. Powinieneś również przyjrzeć się, jak formatowanie kodu działa na pytania / odpowiedzi.
Jonathon Reinhart
-4

Interfejsy API refleksji

Istnieje kilka interfejsów API refleksji, które zwracają klasy, ale dostęp do nich można uzyskać tylko wtedy, gdy klasa została już uzyskana bezpośrednio lub pośrednio.

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()

Zwraca wszystkie klasy publiczne, interfejsy i wyliczenia, które są członkami klasy, w tym elementy odziedziczone.

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

Znak zawiera dwie klasy składowe Character.Subset i
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

mieć klasę zamykającą.

        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
źródło
2
Czy wiesz, że opublikowałeś swoją odpowiedź jako całkowity monolityczny blok kodu? Oświadczeń nie należy formatować jako cytatów ...
Massimiliano Kraus,