Como se pode obter o nome da classe a partir de um método estático nessa classe. Por exemplo
public class MyClass {
public static String getClassName() {
String name = ????; // what goes here so the string "MyClass" is returned
return name;
}
}
Para contextualizar, na verdade, quero retornar o nome da classe como parte de uma mensagem em uma exceção.
try{ throw new RuntimeEsception();} catch(RuntimeEcxeption e){return e.getstackTrace()[1].getClassName();
}Respostas:
Para oferecer suporte à refatoração corretamente (renomear classe), você deve usar:
ou (graças a @James Van Huis ):
fonte
Faça o que o kit de ferramentas diz. Não faça nada parecido com isto:
fonte
getClass
retorna o tipo de tempo de execução, portanto, não pode ser estático.No Java 7+, você pode fazer isso nos métodos / campos estáticos:
fonte
Reflection.getCallerClass()
. Mas dá um aviso sobre estar nos pacotes 'sol'. Portanto, essa pode ser uma solução melhor.Reflection.getCallerClass()
coisa não oficial . É um pouco complicado para sua operação trivial, ou sejaOptional<Class<?>> myself = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) .walk(s -> s.map(StackWalker.StackFrame::getDeclaringClass) .findFirst());
, mas é claro, isso está relacionado ao fato de que será muito mais poderoso.Portanto, temos uma situação em que precisamos obter estaticamente um objeto de classe ou um nome completo / simples de classe sem um uso explícito de
MyClass.class
sintaxe.Pode ser realmente útil em alguns casos, por exemplo, instância de logger para o kotlin funções de nível superior (neste caso, o kotlin cria uma classe Java estática não acessível a partir do código kotlin).
Temos algumas variantes diferentes para obter essas informações:
new Object(){}.getClass().getEnclosingClass();
observado por Tom Hawtin - tackline
getClassContext()[0].getName();
doSecurityManager
observado por Christoffer
new Throwable().getStackTrace()[0].getClassName();
por count ludwig
Thread.currentThread().getStackTrace()[1].getClassName();
de Keksi
e finalmente incrível
MethodHandles.lookup().lookupClass();
de Rein
Eu preparei um jmh referência para todas as variantes e resultados são:
Conclusões
Disponível apenas desde Java 7 e Android API 26!
Se você precisar dele em muitos lugares e não quiser que seu bytecode inche devido a inúmeras classes anônimas -
SecurityManager
é seu amigo (terceira melhor opção).Mas você não pode simplesmente ligar
getClassContext()
- está protegido naSecurityManager
classe. Você precisará de alguma classe auxiliar como esta:getStackTrace()
exceção from ou noThread.currentThread()
. Muito ineficiente e pode retornar apenas o nome da classe como aString
, não aClass<*>
instância.PS
Se você deseja criar uma instância do logger para utilitários estáticos do kotlin (como eu :), você pode usar este auxiliar:
Exemplo de uso:
fonte
Esta instrução funciona bem:
fonte
Thread.getStackTrace()
verá que ele não faz nada alémreturn (new Exception()).getStackTrace();
de ser chamado nocurrentThread()
. Portanto, a solução do @count ludwig é a maneira mais direta de conseguir o mesmo.Você poderia fazer algo realmente agradável usando JNI assim:
MyObject.java:
então:
então:
MyObject.c:
Em seguida, compile o C em uma biblioteca compartilhada chamada
libclassname.so
e execute o java!* risada
fonte
Java_MyObject_getClassName
tem o nome incorporado. A maneira de contornar isso é usar o JNIRegisterNatives
. Claro que você teria que alimentar isso com o JNIFindClass(env, 'com/example/MyObject')
, então também não há vitória.private static final String TAG = "MyClass"
ouprivate static final String TAG = MyClass.class.getSimpleName();
O segundo é mais amigável para renomear classe global usando um IDE.Eu uso isso para iniciar o Log4j Logger na parte superior das minhas classes (ou fazer anotações).
PRO: Throwable já está carregado e você pode economizar recursos ao não usar o SecurityManager "IO pesado".
CON: Alguma pergunta sobre se isso funcionará para todas as JVMs.
fonte
Abuse o SecurityManager
Ou, se não estiver definido, use uma classe interna que a estenda (exemplo abaixo vergonhosamente copiado do HowTo do Real ):
fonte
Se você quiser o nome completo do pacote, chame:
Se você deseja apenas o último elemento, chame:
fonte
O uso verboso da classe de quem chama
MyClass.class.getName()
realmente faz o trabalho, mas é propenso a copiar / colar erros se você propagar esse código para várias classes / subclasses onde você precisa desse nome de classe.E a receita de Tom Hawtin na verdade não é ruim, basta cozinhá-lo da maneira certa :)
Caso você tenha uma classe base com um método estático que pode ser chamado de subclasses e esse método estático precise conhecer a classe do chamador real, isso pode ser alcançado da seguinte maneira:
fonte
Uma solução segura para refatoração, recortar e colar que evita a definição de classes ad-hoc abaixo.
Escreva um método estático que recupere o nome da classe, tendo o cuidado de incluir o nome da classe no nome do método:
depois, lembre-o no seu método estático:
A segurança da refatoração é dada ao evitar o uso de strings, a segurança de recortar e colar é concedida porque, se você recortar e colar o método de chamada, não encontrará o getMyClassName () na classe "MyClass2" de destino, sendo forçado a redefini-lo e atualizá-lo.
fonte
Desde a pergunta Algo como `this.class` em vez de` ClassName.class`? está marcado como duplicado para este (que é discutível porque essa pergunta é sobre a classe e não o nome da classe), estou postando a resposta aqui:
É importante definir
thisClass
como privado porque:1) não deve ser herdado: as classes derivadas devem definir suas próprias
thisClass
ou produzir uma mensagem de erro2) as referências de outras classes devem ser feitas como
ClassName.class
antesClassName.thisClass
.Com
thisClass
definido, o acesso ao nome da classe se torna:fonte
Eu precisava do nome da classe nos métodos estáticos de várias classes, então implementei uma Classe JavaUtil com o seguinte método:
Espero que ajude!
fonte
Eu usei essas duas abordagens para ambos
static
e onon static
cenário:Classe principal:
Como fornecer o nome da classe:
maneira não estática:
Maneira estática:
fonte
Se você estiver usando reflexão, poderá obter o objeto Method e, em seguida:
Para obter o próprio método, você provavelmente pode usar:
fonte
Class.forName("class name")
Já tendo lhe dado uma aula. Por que você deseja recuperá-lo via Method?