Obtendo o nome de uma subclasse de dentro de uma super classe
-
26-09-2019 - |
Pergunta
Digamos que eu tenho uma classe base chamada Entity
. Nessa classe, tenho um método estático para recuperar o nome da classe:
class Entity {
public static String getClass() {
return Entity.class.getClass();
}
}
Agora tenho outra aula estendê -lo.
class User extends Entity {
}
Eu quero obter o nome da classe do usuário:
System.out.println(User.getClass());
Meu objetivo é ver a saída "com.packagename.user" no console, mas, em vez disso, vou acabar com "com.packagename.entity", já que a classe de entidade está sendo referenciada diretamente do método estático.
Se esse não fosse um método estático, isso poderia ser facilmente resolvido usando o this
palavra -chave dentro do Entity
classe (ou seja: return this.class.getClass()
). No entanto, preciso que esse método permaneça estático. Alguma sugestão sobre como abordar isso?
Solução
Não é possivel. Os métodos estáticos não são polimórficos de tempo de execução de forma alguma. É absolutamente impossível distinguir esses casos:
System.out.println(Entity.getClass());
System.out.println(User.getClass());
Eles compilam com o mesmo código de byte (assumindo que o método é definido em Entity
).
Além disso, como você chamaria esse método de uma maneira que faria sentido para ser polimórfico?
Outras dicas
Não faça do método estático. A questão é que quando você invoca getClass()
Você está chamando o método na super classe - os métodos estáticos não são herdados. Além Object.getClass()
, o que é confuso.
Se você precisar registrar o nome da classe na superclasse, use
return this.getClass().getName();
Isso retornará "entidade" quando você tiver um Entity
instância, "usuário" quando você tem um User
instância, etc.
Sua pergunta é ambígua, mas até onde posso dizer que você quer saber a classe atual de um método estático. O fato de as classes herdarem um do outro é irrelevante, mas, pelo bem da discussão, também a implementei dessa maneira.
class Parent { public static void printClass() { System.out.println(Thread.currentThread().getStackTrace()[2].getClassName()); } } public class Test extends Parent { public static void main(String[] args) { printClass(); } }
Isso funciona para mim
this.getClass().asSubclass(this.getClass())
Mas não tenho certeza de como funciona.
A superclasse nem deve saber da existência da subclasse, muito menos operações com base no nome totalmente qualificado da subclasse. Se você precisar de operações com base no que é a classe exata e não pode desempenhar a função necessária por herança, você deve fazer algo nesse sentido:
public class MyClassUtil
{
public static String doWorkBasedOnClass(Class<?> clazz)
{
if(clazz == MyNormalClass.class)
{
// Stuff with MyNormalClass
// Will not work for subclasses of MyNormalClass
}
if(isSubclassOf(clazz, MyNormalSuperclass.class))
{
// Stuff with MyNormalSuperclass or any subclasses
}
// Similar code for interface implementations
}
private static boolean isSubclassOf(Class<?> subclass, Class<?> superclass)
{
if(subclass == superclass || superclass == Object.class) return true;
while(subclass != superclass && subclass != Object.class)
{
subclass = subclass.getSuperclass();
}
return false;
}
}
(Código não testado)
Esta classe também não sabe sobre suas próprias subclasses, mas usa o Class
classe para executar operações. Muito provavelmente, ainda estará fortemente ligado às implementações (geralmente uma coisa ruim, ou se não é ruim, não é especialmente Boa), mas acho que uma estrutura como essa é melhor do que uma superclasse, descobrindo quais são todas as suas subclasses.
Por que você deseja implementar seu próprio método getClass ()? Você pode simplesmente usar
System.out.println(User.class);
Editar (para elaborar um pouco): você deseja que o método seja estático. Nesse caso, você deve chamar o método na classe cujo nome de classe você deseja, seja a subclasse ou a super classe. Então, em vez de ligar MyClass.getClass()
, você pode simplesmente ligar MyClass.class
ou MyClass.class.getName()
.
Além disso, você está criando um static
método com a mesma assinatura que o Object.getClass()
Método da instância, que não compilará.
- Crie uma variável de sequência de membros na superclasse.
- Adicione o this.getClass (). GetName () a um construtor que armazena o valor na variável String de membro.
- Crie um getter para retornar o nome.
Cada vez que a classe estendida é instanciada, seu nome será armazenado na string e acessível com o getter.
Um método estático está associado a uma classe, não a um objeto específico.
Considere como isso funcionaria se houvesse várias subclasses - por exemplo, o administrador também é uma entidade. Como seu método de entidade estática, associado apenas à classe da entidade, saberia qual subclasse você queria?
Você poderia:
- Use o método getClass () existente.
- Passe um argumento para o seu método estático getClass () e chame um método de instância nesse objeto.
- Torne seu método não estático e renomeie-o.
Se eu entender sua pergunta corretamente, acho que a única maneira de conseguir o que deseja é reimplementar o método estático em cada subclasse, por exemplo:
class Entity {
public static String getMyClass() {
return Entity.class.getName();
}
}
class Derived extends Entity {
public static String getMyClass() {
return Derived.class.getName();
}
}
Isso imprimirá o pacote. Bagunçado, mas ei, se essas são suas restrições ...
Se eu estou acertando, você deseja usar sua sub -classe na classe base no método estático, acho que você pode fazer isso passando um parâmetro de classe para o método
class Entity {
public static void useClass(Class c) {
System.out.println(c);
// to do code here
}
}
class User extends Entity {
}
class main{
public static void main(String[] args){
Entity.useClass(Entity.class);
}
}
Meu contexto: entidade superclass com subclasses para objetos XML. Minha solução: crie uma variável de classe na superclasse
Class<?> claz;
Então, na subclasse, eu definiria a variável da superclasse no construtor
public class SubClass {
public SubClass() {
claz = this.getClass();
}
}
É muito simples feito por
User.getClass (). GetSuperclass ()