Como determinar a classe de um objeto?


510

Se classe Be classe Cestendem classe Ae eu tenho um objeto do tipo Bou C, como posso determinar de que tipo é uma instância?


14
@ starblue Fundição seria a primeira coisa que vem à mente. Duvido que a instância do operador exista se não houver necessidade.
b1nary.atr0phy

@ b1nary.atr0phy não seria bom usar primeiro a isnancia do operador. Se há um elenco para um tipo incompatível, acredito que irá resultar em uma ClassCastException
committedandroider

Respostas:


801
if (obj instanceof C) {
//your code
}

31
É útil anotar a verificação inversa ou como verificar se um Objeto NÃO é uma instância de uma classe:if(!(obj instanceof C))
Dzhuneyt

32
Eu acredito que o método getClass () é a resposta para a pergunta original. Nesse caso (a instância obj de A) também forneceria saída "true", mas a intenção é encontrar a classe de tempo de execução do objeto na imagem. Se Parent1 for estendido por Child1 e Child2, tente o seguinte code Child1 child1 = new Child1 (); Parent1 parentChild = new Child2 (); Filho2 filho2 = novo Filho2 (); (instância child1 do Parent1); (instância child1 de Child1); (instância parentChild de Child2); (parentChild instanceof Parent1); (instância parentChild de Child1); code , pode limpar a intenção de instanceof.
Bhavesh Agarwal

Definitivamente uma alternativa para a construção de uma interface
JohnMerlino

3
E se eu tiver duas classes implementando interface única? Como faço para distinguir a classe exata do objeto?
olyv

3
Uma coisa, porém, não funciona se obj for nulo. A solução seria então ParentInterface.class.isAssignableFrom (Child.class)
alexbt


178

Várias respostas corretas foram apresentadas, mas ainda existem mais métodos: Class.isAssignableFrom()e simplesmente tentar lançar o objeto (que pode lançar a ClassCastException).

Formas possíveis resumidas

Vamos resumir as maneiras possíveis de testar se um objeto objé uma instância do tipo C:

// Method #1
if (obj instanceof C)
    ;

// Method #2
if (C.class.isInstance(obj))
    ;

// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
    ;

// Method #4
try {
    C c = (C) obj;
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

// Method #5
try {
    C c = C.class.cast(obj);
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

Diferenças no nullmanuseio

Há uma diferença no nullmanuseio:

  • Nos 2 primeiros métodos, as expressões avaliam falsese objé null( nullnão é instância de nada).
  • O terceiro método jogaria um NullPointerExceptionobviamente.
  • Os métodos 4 e 5, pelo contrário, aceitam nullporque nullpodem ser convertidos para qualquer tipo!

Lembrar: null não é uma instância de nenhum tipo, mas pode ser convertida para qualquer tipo.

Notas

  • Class.getName()não deve ser usado para executar um teste "is-instance-of" porque, se o objeto não for do tipo, Cmas uma subclasse dele, ele pode ter um nome e pacote completamente diferentes (portanto, os nomes das classes obviamente não coincidem), mas é ainda do tipo C.
  • Pela mesma herança, o motivo Class.isAssignableFrom()não é simétrico :
    obj.getClass().isAssignableFrom(C.class)retornaria falsese o tipo de objfosse uma subclasse de C.

6
Este é realmente um excelente resumo de muitas das armadilhas dos diferentes métodos. Obrigado por uma escrita tão completa!
Kelsin 8/08/2015

32

Você pode usar:

Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object

HTH. Mas acho que na maioria das vezes não é uma boa prática usar isso para controlar o fluxo ou algo semelhante ...


Eu o usei para criar um logger genérico; por isso, enviei um objeto para o logger e ele faz logon, dependendo do nome da classe do objeto, em vez de fornecer a tag ou a string de log sempre. obrigado
MBH

24

Qualquer uso de qualquer um dos métodos sugeridos é considerado um cheiro de código, baseado em um projeto de OO ruim.

Se o seu design for bom, você não precisará usar getClass()ou instanceof.

Qualquer um dos métodos sugeridos servirá, mas apenas algo a ter em mente, em termos de design.


3
Sim, provavelmente 99% dos usos de getClass e instanceof podem ser evitados com chamadas de método polimórficas.
Bill o Lagarto

3
Eu concordo. Neste caso, estou trabalhando com objetos gerados a partir de xml, seguindo um esquema mal projetado, do qual não possuo propriedade.
transportador

28
Não necessariamente. Às vezes, a separação de interfaces é boa. Há momentos em que você deseja saber se A é um B, mas não deseja tornar obrigatório que A seja um B, pois somente A é necessário para a maioria das funcionalidades - B possui funcionalidade opcional.
MetroidFan2002 12/02/09

8
Além disso, há momentos em que você precisa garantir que o objeto seja da mesma classe com a qual você está comparando; por exemplo, eu gosto de substituir o método equals do objeto quando crio minha própria classe. Eu sempre verifico que o objeto que entra é da mesma classe.
precisa

58
Além disso, eu diria que dizer às pessoas que algo está ruim sem explicar exatamente o porquê ou fazer uma referência a um artigo, livro ou qualquer outro recurso em que a questão seja explicada é considerada não construtiva. Portanto, e sabendo que estou no StackOverflow, não sei por que as pessoas votaram tanto nessa resposta. Algo está mudando aqui ...
Adrián Pérez

15

Podemos usar a reflexão neste caso

objectName.getClass().getName();

Exemplo:-

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String name = request.getClass().getName();
}

Nesse caso, você obterá o nome da classe que o objeto passa para a HttpServletRequestvariável de referência de interface.


isto está correto. usando apenas obj.getClass()retornará o className, prefixex pela palavraclass
x6iae

request.getClass().getName();imprime todo o pacote! juntamente com o nome da classe
shareef

13

Também existe um .isInstancemétodo na Classclasse " ". se você obtiver a classe de um objeto via, myBanana.getClass()poderá ver se o objeto myAppleé uma instância da mesma classe que myBananavia

myBanana.getClass().isInstance(myApple)

1

verificar com isinstance()não seria suficiente se você quiser saber em tempo de execução. usar:

if(someObject.getClass().equals(C.class){
    // do something
}

0

Eu uso a função blow na minha classe GeneralUtils, verifique se pode ser útil

    public String getFieldType(Object o) {
    if (o == null) {
        return "Unable to identify the class name";
    }
    return o.getClass().getName();
}

0

Usei os genéricos do Java 8 para obter qual é a instância do objeto em tempo de execução, em vez de precisar usar o caso do comutador

 public <T> void print(T data) {
    System.out.println(data.getClass().getName()+" => The data is " + data);
}

transmita qualquer tipo de dado e o método imprimirá o tipo de dado que você passou enquanto o chamava. por exemplo

    String str = "Hello World";
    int number = 10;
    double decimal = 10.0;
    float f = 10F;
    long l = 10L;
    List list = new ArrayList();
    print(str);
    print(number);
    print(decimal);
    print(f);
    print(l);
    print(list);

A seguir está a saída

java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.