Как можно получить имя класса из статического метода в этом классе. Например
public class MyClass {
public static String getClassName() {
String name = ????; // what goes here so the string "MyClass" is returned
return name;
}
}
Чтобы поместить это в контекст, я на самом деле хочу вернуть имя класса как часть сообщения в исключении.
try{ throw new RuntimeEsception();} catch(RuntimeEcxeption e){return e.getstackTrace()[1].getClassName();
}Ответы:
Чтобы правильно поддерживать рефакторинг (переименовать класс), вы должны использовать либо:
или (спасибо @James Van Huis ):
источник
Делайте то, что говорит инструментарий. Не делайте ничего подобного
источник
getClass
возвращает тип среды выполнения, поэтому не может быть статическим.В Java 7+ вы можете сделать это в статическом методе / полях:
источник
Reflection.getCallerClass()
. Но это предупреждает о нахождении в «солнечных» пакетах. Так что это может быть лучшим решением.Reflection.getCallerClass()
вещь. Это немного сложно для его тривиальной операции, т. Е.Optional<Class<?>> myself = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) .walk(s -> s.map(StackWalker.StackFrame::getDeclaringClass) .findFirst());
, Конечно, это связано с тем, что он будет гораздо более мощным.Итак, у нас есть ситуация, когда нам нужно статически получить объект класса или полное / простое имя класса без явного использования
MyClass.class
синтаксиса.В некоторых случаях это может быть очень удобно, например, для Котлин функции верхнего уровня (в этом случае kotlin создает статический класс Java, недоступный из кода kotlin).
У нас есть несколько вариантов получения этой информации:
new Object(){}.getClass().getEnclosingClass();
отметил Том Хотин - tackline
getClassContext()[0].getName();
отSecurityManager
отмеченного Кристоффером
new Throwable().getStackTrace()[0].getClassName();
по подсчетам людвиг
Thread.currentThread().getStackTrace()[1].getClassName();
из Кекси
и, наконец, круто
MethodHandles.lookup().lookupClass();
от Рейна
Я подготовил JMH Эталоном для всех вариантов и результатов являются:
Выводы
Доступно только с Java 7 и Android API 26!
Если вам это нужно во многих местах и вы не хотите, чтобы ваш байт-код раздулся из-за множества анонимных классов -
SecurityManager
это ваш друг (третий лучший вариант).Но вы не можете просто позвонить
getClassContext()
- он защищен вSecurityManager
классе. Вам понадобится некоторый вспомогательный класс, подобный этому:getStackTrace()
исключении from илиThread.currentThread()
. Очень неэффективно и может возвращать только имя класса как, аString
не какClass<*>
экземпляр.PS
Если вы хотите создать экземпляр logger для статических утилит kotlin (как я :), вы можете использовать этот помощник:
Пример использования:
источник
Эта инструкция отлично работает:
источник
Thread.getStackTrace()
то увидите, что он ничего не делает, кроме какreturn (new Exception()).getStackTrace();
в случае вызова наcurrentThread()
. Таким образом, решение @count ludwig - более прямой способ добиться того же.Вы можете сделать что-то действительно приятное, используя JNI, например:
MyObject.java:
затем:
затем:
MyObject.c:
Затем скомпилируйте C в общую библиотеку с именем
libclassname.so
и запустите Java!* смешок
источник
Java_MyObject_getClassName
имеет встроенное имя. Обходной путь - использовать JNIRegisterNatives
. Конечно, вам придется кормить это с JNIFindClass(env, 'com/example/MyObject')
, так что там тоже нет победы.private static final String TAG = "MyClass"
либоprivate static final String TAG = MyClass.class.getSimpleName();
второй вариант более удобен для глобального переименования классов с использованием IDE.Я использую это, чтобы инициировать Log4j Logger в верхней части моих классов (или аннотировать).
PRO: Throwable уже загружен, и вы можете сэкономить ресурсы, не используя «IO heavy» SecurityManager.
CON: Некоторые вопросы относительно того, будет ли это работать для всех JVM.
источник
Злоупотребление SecurityManager
Или, если не установлен, используйте внутренний класс, который расширяет его (пример ниже постыдно скопирован из HowTo Real ):
источник
Если вам нужно полное имя пакета с ним, позвоните:
Если вы хотите только последний элемент, позвоните:
источник
Дословное использование класса вызывающего, как на
MyClass.class.getName()
самом деле, делает свою работу, но склонен к ошибкам копирования / вставки, если вы распространяете этот код среди многочисленных классов / подклассов, где вам нужно это имя класса.И рецепт Тома Хоутина на самом деле неплохой, нужно просто правильно его приготовить :)
Если у вас есть базовый класс со статическим методом, который можно вызывать из подклассов, и этот статический метод должен знать фактический класс вызывающего, это может быть достигнуто следующим образом:
источник
Безопасное для рефакторинга, вырезанное и вставленное решение, которое позволяет избежать определения специальных классов ниже.
Напишите статический метод, который восстанавливает имя класса, стараясь включить имя класса в имя метода:
затем вспомните это в вашем статическом методе:
Безопасность рефакторинга обеспечивается за счет исключения использования строк, безопасность «вырезать и вставить» предоставляется, потому что если вы вырезаете и вставляете метод вызывающей стороны, вы не найдете getMyClassName () в целевом классе «MyClass2», поэтому вам придется переопределить и обновить его.
источник
Поскольку вопрос Что-то вроде `this.class` вместо` ClassName.class`? помечен как дубликат для этого (что спорно , потому что речь идет о классе , а не имя класса), я отправляю ответ здесь:
Важно определить
thisClass
как частное, потому что:1) оно не должно быть унаследовано: производные классы должны либо определять свои собственные,
thisClass
либо выдавать сообщение об ошибке2) ссылки на другие классы должны быть сделаны,
ClassName.class
а неClassName.thisClass
.С
thisClass
определением, доступ к имени класса становится:источник
Мне нужно было имя класса в статических методах нескольких классов, поэтому я реализовал JavaUtil Class следующим методом:
Надеюсь, это поможет!
источник
Я использовал эти два подхода для обоих
static
иnon static
сценария:Основной класс:
Как предоставить имя класса:
нестатический способ:
Статический способ:
источник
Если вы используете отражение, вы можете получить объект Method и затем:
Чтобы получить сам метод, вы, вероятно, можете использовать:
источник
Class.forName("class name")
уже дать вам класс. Почему вы хотите получить его с помощью метода?