¿Cómo determinar la clase de un objeto?


510

Si clase By clase Cextienden clase Ay tengo un objeto de tipo Bo C, ¿cómo puedo determinar de qué tipo es una instancia?


14
@starblue Casting sería lo primero que me viene a la mente. Dudo que el operador de instancia de existiría si no fuera necesario.
b1nary.atr0phy

@ b1nary.atr0phy, ¿no sería bueno utilizar primero el operador isntanceof? Si hay un elenco a un tipo incompatible, creo que eso dará como resultado una ClassCastException
committedandroider

Respuestas:


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

31
Es útil observar la verificación inversa o cómo verificar si un Objeto NO es una instancia de una clase:if(!(obj instanceof C))
Dzhuneyt

32
Creo que el método getClass () es la respuesta a la pregunta original. En este caso (obj instanceof A) también daría una salida "verdadera", pero la intención es encontrar la clase de tiempo de ejecución del objeto en la imagen. Si Parent1 y Child2 amplían Parent1, intente lo siguiente code Child1 child1 = new Child1 (); Parent1 parentChild = new Child2 (); Child2 child2 = new Child2 (); (instancia child1 de Parent1); (child1 instanceof Child1); (parentChild instanceof Child2); (parentChild instanceof Parent1); (parentChild instanceof Child1); code , puede borrar la intención de instancia de.
Bhavesh Agarwal

Definitivamente una alternativa a la construcción de una interfaz
JohnMerlino

3
¿Qué sucede si tengo dos clases que implementan una interfaz única? ¿Cómo distingo la clase exacta del objeto?
olyv

3
Sin embargo, una cosa no funciona si obj es nulo. La solución sería ParentInterface.class.isAssignableFrom (Child.class)
alexbt


178

Se presentaron múltiples respuestas correctas, pero todavía hay más métodos: Class.isAssignableFrom()y simplemente intentar lanzar el objeto (que podría arrojar un ClassCastException).

Posibles formas resumidas

Resumamos las posibles formas de probar si un objeto objes una instancia de 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) {
}

Diferencias en el nullmanejo

Sin nullembargo, hay una diferencia en el manejo:

  • En los primeros 2 métodos, las expresiones evalúan falsesi objes null( nullno es una instancia de nada).
  • El tercer método arrojaría un NullPointerExceptionobviamente.
  • Los métodos 4 y 5, por el contrario, aceptan nullporque nullse pueden lanzar a cualquier tipo.

Para recordar: null no es una instancia de ningún tipo, pero se puede convertir a cualquier tipo.

Notas

  • Class.getName()no debe usarse para realizar una prueba "es-instancia-de" porque si el objeto no es de tipo Csino una subclase de él, puede tener un nombre y un paquete completamente diferentes (por lo tanto, los nombres de clase obviamente no coincidirán) pero es Todavía de tipo C.
  • Por la misma razón de herencia Class.isAssignableFrom()no es simétrica :
    obj.getClass().isAssignableFrom(C.class)regresaría falsesi el tipo de objes una subclase de C.

66
Este es un gran resumen de muchas de las dificultades en los diferentes métodos. ¡Gracias por una redacción tan completa!
Kelsin

32

Puedes usar:

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

HTH Pero creo que la mayoría de las veces no es una buena práctica usar eso para controlar el flujo o algo similar ...


Lo usé para crear un registrador genérico, así que envié un objeto al registrador, y se registra dependiendo del nombre de la clase del objeto, en lugar de dar una etiqueta de registro o una cadena de registro cada vez. gracias
MBH

24

Cualquier uso de cualquiera de los métodos sugeridos se considera un olor a código que se basa en un mal diseño de OO.

Si su diseño es bueno, no debería necesitar usar getClass()o instanceof.

Cualquiera de los métodos sugeridos servirá, pero es algo a tener en cuenta, en cuanto al diseño.


3
Sí, probablemente el 99% de los usos de getClass e instanceof se pueden evitar con llamadas a métodos polimórficos.
Bill the Lizard

3
estoy de acuerdo. en este caso, estoy trabajando con objetos generados a partir de xml siguiendo un esquema mal diseñado del que no soy propietario.
transportista

28
No nessecarily. A veces la separación de las interfaces es buena. Hay momentos en los que desea saber si A es un B, pero no desea hacer obligatorio que A sea un B, ya que solo se requiere A para la mayoría de las funciones: B tiene una funcionalidad opcional.
MetroidFan2002

8
Además, hay momentos en los que necesita asegurarse de que el objeto sea de la misma clase con la que se está comparando; Por ejemplo, me gusta anular el método de igualdad de objetos cuando creo mi propia clase. Siempre verifico que el objeto que entra es de la misma clase.
StackOverflowed

58
Además, diría que decirle a la gente algo malo sin explicar exactamente por qué o dar una referencia a un documento, libro o cualquier otro recurso en el que se explique el problema no se considera constructivo. Por lo tanto, y sabiendo que estoy en StackOverflow, no sé por qué la gente ha votado tanto por esta respuesta. Algo está cambiando aquí ...
Adrián Pérez

15

Podemos usar la reflexión en este caso

objectName.getClass().getName();

Ejemplo:-

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

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

En este caso, obtendrá el nombre de la clase que el objeto pasa a la HttpServletRequestvariable de referencia de la interfaz.


esto es correcto. usar solo obj.getClass()devolverá el className, prefixex por la palabraclass
x6iae

request.getClass().getName();imprime todo el paquete! junto con el nombre de la clase
shareef

13

También hay un .isInstancemétodo en la Classclase " ". si obtiene la clase de un objeto a través de myBanana.getClass(), puede ver si su objeto myApplees una instancia de la misma clase que a myBananatravés de

myBanana.getClass().isInstance(myApple)

1

consultar con isinstance()no sería suficiente si quieres saber en tiempo de ejecución. utilizar:

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

0

Uso la función de soplado en mi clase GeneralUtils, verifique que puede ser útil

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

0

Usé genéricos de Java 8 para obtener cuál es la instancia del objeto en tiempo de ejecución en lugar de tener que usar la caja del interruptor

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

pase cualquier tipo de datos y el método imprimirá el tipo de datos que pasó mientras lo llamaba. p.ej

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

Siguiente es la salida

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 []
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.