Comparando tipos de clases en Java

6 minutos de lectura

Avatar de usuario de Carven
tallado

Quiero comparar el tipo de clase en Java.

Pensé que podría hacer esto:

class MyObject_1 {}
class MyObject_2 extends MyObject_1 {}

public boolean function(MyObject_1 obj) {
   if(obj.getClass() == MyObject_2.class) System.out.println("true");
}

Quería comparar en caso de que el obj pasado a la función se extendiera desde MyObject_1 o no. Pero esto no funciona. Parece que el método getClass() y .class brindan diferentes tipos de información.

¿Cómo puedo comparar dos tipos de clase sin tener que crear otro objeto ficticio solo para comparar el tipo de clase?

  • Esta pregunta es confusa y me confundió sobre la forma en que “==” funciona en caso de comparar clases/interfaces. El ejemplo debe ser autónomo. ¡Lo que pase a su función debería estar en el ejemplo!

    – croraf

    2 de enero de 2017 a las 13:35

Avatar de usuario de Thor
thor

Prueba esto:

MyObject obj = new MyObject();
if(obj instanceof MyObject){System.out.println("true");} //true

Debido a la herencia, esto también es válido para las interfaces:

class Animal {}
class Dog extends Animal {}    

Dog obj = new Dog();
Animal animal = new Dog();
if(obj instanceof Animal){System.out.println("true");} //true
if(animal instanceof Animal){System.out.println("true");} //true
if(animal instanceof Dog){System.out.println("true");} //true

Para leer más sobre la instancia de: http://mindprod.com/jgloss/instanceof.html

  • Pero, ¿qué sucede si quiero verificar que Animal es una instancia de Dog? ¿Todavía es posible? Diga: public void check(Animal obj) { if(obj instanceof Dog){System.out.println(“true”);} } ¿Sigue siendo posible?

    – tallado

    27 de mayo de 2011 a las 8:50


  • @xEnON: Esto es posible, pero siempre devolverá falso. No puede verificar si una interfaz es una instancia de una clase concreta.

    – thor

    27 de mayo de 2011 a las 8:56

  • Entonces, si tengo una función que hace uso de esta función de polimorfismo, ¿no puedo verificar su tipo de clase exacto en tiempo de ejecución?

    – tallado

    27 mayo 2011 a las 9:00

  • Lo siento, está mal que esto siempre devuelva falso. No he leído tu comentario con suficiente atención. Mira mi respuesta.

    – thor

    27 de mayo de 2011 a las 9:04


  • Oh… Entiendo que está mal y devolverá falso. Estaba pensando que si hay otra forma de lograr este objetivo.

    – tallado

    27 de mayo de 2011 a las 9:12

Si no quiere o no puede usar instanceofluego comparar con equals:

 if(obj.getClass().equals(MyObject.class)) System.out.println("true");

Por cierto, es extraño porque los dos Class las instancias en su declaración realmente deberían ser las mismas, al menos en su código de ejemplo. Ellos mayo ser diferente si:

  • las clases tienen el mismo nombre corto pero están definidas en diferentes paquetes
  • las clases tienen el mismo nombre completo pero son cargadas por diferentes cargadores de clases.

  • Me pregunto por qué esta respuesta tiene tantos votos a favor (supongo que una de las razones es que la pregunta se cambió después de que se publicó esta respuesta). java.lang.Class no anula Object.equalslo que significa que para dos no nulos cls1 y cls2: cls1.equals(cls2) es verdadera si y solo si cls1 == cls2 es verdad. Lo que significa que el enfoque propuesto es el mismo que describió el iniciador del tema.

    – Valentín Kovalenko

    10 de febrero de 2019 a las 1:06

Avatar de usuario de Sean Patrick Floyd
sean patrick floyd

se imprime true en mi maquina Y debería, de lo contrario, nada en Java funcionaría como se esperaba. (Esto se explica en el JLS: 4.3.4 Cuando los tipos de referencia son iguales)

¿Tiene varios cargadores de clases en su lugar?


Ah, y en respuesta a este comentario:

Me doy cuenta de que tengo un error tipográfico en mi pregunta. Debería ser así:

MyImplementedObject obj = new MyImplementedObject ();
if(obj.getClass() == MyObjectInterface.class) System.out.println("true");

MyImplementedObject implementa MyObjectInterface En otras palabras, lo estoy comparando con sus objetos implementados.

OK, si quieres comprobar que puedes hacer:

if(MyObjectInterface.class.isAssignableFrom(obj.getClass()))

o el mucho más conciso

if(obj instanceof MyobjectInterface)

  • Me doy cuenta de que tengo un error tipográfico en mi pregunta. Debería ser así: MyImplementedObject obj = new MyImplementedObject (); if(obj.getClass() == MyObjectInterface .class) System.out.println(“true”); MyImplementedObject implementa MyObjectInterface En otras palabras, lo estoy comparando con sus objetos implementados.

    – tallado

    27 de mayo de 2011 a las 8:33


  • He actualizado mi publicación con el código correcto que quise decir. Perdón por la confusion.

    – tallado

    27 de mayo de 2011 a las 8:40

  • ¡¡Gracias!! En su actualización, debido a que obj se extiende desde MyObjectInterface, comparar obj con MyObjectInterface aún puede estar bien. Pero qué pasa si quisiera comparar en la dirección opuesta. Por ejemplo, si obj es MyObject_1. Y hay un MyObject_2 extendido desde MyObject_1. Luego, quería verificar si obj es realmente de MyObject_2 o no, ¿funcionaría esto todavía? Esta es la actualización en mi publicación de preguntas.

    – tallado

    27 de mayo de 2011 a las 8:48

Como se dijo anteriormente, su código funcionará a menos que tenga las mismas clases cargadas en dos cargadores de clases diferentes. Esto podría suceder en caso de que necesite varias versiones de la misma clase en la memoria al mismo tiempo, o si está haciendo algo raro de compilación sobre la marcha (como yo).

En este caso, si desea considerarlos como la misma clase (lo que podría ser razonable según el caso), puede hacer coincidir sus nombres para compararlos.

public static boolean areClassesQuiteTheSame(Class<?> c1, Class<?> c2) {
  // TODO handle nulls maybe?
  return c1.getCanonicalName().equals(c2.getCanonicalName());
}

Tenga en cuenta que esta comparación hará exactamente lo que hace: comparar nombres de clases; No creo que pueda transmitir de una versión de una clase a la otra, y antes de reflexionar, es posible que desee asegurarse de que haya una buena razón para el problema del cargador de clases.

Comparando un objeto con una clase usando instanceOf o… ya está respondida.

Si tiene dos objetos y desea comparar sus tipos con El uno al otropuedes usar:

if (obj1.getClass() == obj2.getClass()) {
   // Both have the same type
}

Avatar de usuario de Sam
Sam

Si tuviera dos cadenas y las comparara usando == llamando al método getClass() en ellas, devolvería verdadero. Lo que obtienes es una referencia sobre el mismo objeto.

Esto se debe a que ambas son referencias en el mismo objeto de clase. Esto es cierto para todas las clases en una aplicación Java. Java solo carga la clase una vez, por lo que solo tiene una instancia de una clase dada en un momento dado.

String hello  = "Hello";
String world = "world";

if (hello.getClass() == world.getClass()) {
    System.out.println("true");
} // prints true

Avatar de usuario de Max Tardiveau
Max Tardiveau

Hmmm… Tenga en cuenta que Class puede o no implementar equals() — eso no es requerido por la especificación. Por ejemplo, HP Fortify marcará myClass.equals(myOtherClass).

¿Ha sido útil esta solución?