Java - получить имя текущего класса?

272

Все, что я пытаюсь сделать, это получить текущее имя класса, а java добавляет бесполезный бессмысленный $ 1 в конец имени моего класса. Как я могу избавиться от него и вернуть только фактическое имя класса?

String className = this.getClass().getName();
aryaxt
источник
1
Где ты это называешь? Это изнутри анонимного внутреннего класса? Не могли бы вы добавить еще немного кода, который показывает подробности об определении класса и откуда эта строка вызывается?
Plajjimbo
8
Итак, все, что вы хотите,String className = getClass().getName().substring(0, getClass().getName().indexOf("$"))
josh.trow
9
Если вы получите $1тогда, потому что имя класса $1. Если вы ожидаете чего-то другого, используйте thisправильный класс вместо неправильного.
выступление

Ответы:

248

«$ 1» не является «бесполезным бессмысленным». Если ваш класс анонимный, добавляется номер.

Если вам нужен не сам класс, а его класс, то вы можете его использовать getEnclosingClass(). Например:

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

Вы можете переместить это в некоторый статический служебный метод.

Но обратите внимание, что это не текущее имя класса. Анонимный класс - это другой класс, чем класс, в который он включен. Случай аналогичен для внутренних классов.

Bozho
источник
2
Но что, если включающий класс также является анонимным внутренним классом? Разве вам не нужно рекурсивно получать включающий класс, пока он не вернется null, и использовать последний некласс, который nullвы получили?
Гаррет Уилсон
231

Пытаться,

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

Это будет работать до тех пор, пока вы не используете его в статическом методе.

jesg
источник
1
На самом деле, нет, это не сработает. Этот вопрос указывает на то, что у него есть анонимный внутренний класс, и для этого случая getSimpleName () возвращает""
vikingsteve
48
Несмотря на то, что это не отвечает на этот вопрос, эта публикация SO в настоящее время находится в числе лучших результатов для "get class name java" в Google, и поэтому она все еще полезна для сообщества.
EdgeCaseBerg
6
Он вернет имя без пространства имен пакета. Хороший!
Олег Абражаев
31

Попробуйте использовать это this.getClass().getCanonicalName()или this.getClass().getSimpleName(). Если это анонимный класс, используйтеthis.getClass().getSuperclass().getName()

MirroredFate
источник
На самом деле, это так. В зависимости. Если вы пытаетесь получить имя абстрактного класса, который вы реализуете с помощью анонимного класса, это то, что вы используете.
MirroredFate
для его случая (анонимный класс) простое имя пусто, каноническое имя равно нулю, а суперкласс - Object.
Божо
Да да нет Мои первые два были только предположениями, третье, однако, правильно. Анонимный класс - это подкласс класса, который он реализует. Вот почему они работают. Таким образом, суперкласс является абстрактным классом.
MirroredFate
Странно, разве суперкласс не тот класс, от которого вы наследуете? Обработчик не наследует от моего класса, это просто член
aryaxt
Хм ... Я проверил это, и я понял, что суперкласс анонимного класса является абстрактным классом. Я проверю свою логику ... но поскольку я получаю результат, который имеет смысл, я не думаю, что это я допустил ошибку ...
MirroredFate
10

Вы можете использовать this.getClass().getSimpleName(), например, так:

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();
    }
}
Каруна
источник
4

Сочетание обоих ответов. Также печатает имя метода:

Class thisClass = new Object(){}.getClass();
String className = thisClass.getEnclosingClass().getSimpleName();
String methodName = thisClass.getEnclosingMethod().getName();
Log.d("app", className + ":" + methodName);
SoftDesigner
источник
3

этот ответ запоздал, но я думаю, что есть другой способ сделать это в контексте класса анонимного обработчика.

скажем так:

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

он достигнет того же результата. кроме того, это на самом деле довольно удобно, поскольку каждый класс определяется во время компиляции, поэтому динамичность не нарушается.

Кроме того, если класс действительно является вложенным, т. е. Aфактически окружен B, класс B может быть легко известен как:

B.this.getClass().getName()
Джейсон Ху
источник
2

В вашем примере, thisвероятно, относится к экземпляру анонимного класса. Java дает имя этим классам, добавляя a $numberк имени включающего класса.

Тонио
источник
2
Неанонимные внутренние классы называются Outer $ Inner. Это будет анонимный класс.
Дункан МакГрегор
1

Я предполагаю, что это происходит для анонимного класса. Когда вы создаете анонимный класс, вы фактически создаете класс, который расширяет класс, имя которого вы получили.

«Чистый» способ получить желаемое имя:

Если ваш класс является анонимным внутренним классом, getSuperClass()вам следует указать класс, из которого он был создан. Если вы создали его из интерфейса, чем-то вроде SOL, потому что лучшее, что вы можете сделать, это getInterfaces()предоставить вам более одного интерфейса.

«Хакерский» способ - просто получить имя getClassName()и использовать регулярное выражение для удаления $1.

trutheality
источник
0

Вот вариант Android, но тот же принцип можно использовать и в простой Java.

private static final String TAG = YourClass.class.getSimpleName();
private static final String TAG = YourClass.class.getName();
Ако
источник
-3

Я обнаружил, что это работает для моего кода, однако мой код получает класс из массива в цикле for.

String className="";

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

System.out.print(className); //Use this to test it works
hransom
источник
Это не добавляет ничего, что ни один из других ответов еще не сказал. Вся проблема цикла / массива не имеет значения. Кроме того, вы должны посмотреть, как форматирование кода работает на вопросы / ответы.
Джонатон Рейнхарт
-4

API отражения

Существует несколько API-интерфейсов Reflection, которые возвращают классы, но к ним можно получить доступ, только если класс уже был получен прямо или косвенно.

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

Возвращает все общедоступные классы, интерфейсы и перечисления, которые являются членами класса, включая унаследованные члены.

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

Character содержит два класса-члена Character.Subset и
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

иметь включающий класс.

        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.
арункумар самбу
источник
2
Знаете ли вы, что вы опубликовали свой ответ как полный монолитный блок кода? Заявления не должны быть отформатированы как кавычки ...
Массимилиано Краус