2012-05-05 12 views
21

¿Hay necesidad de comparar dos objetos según la clase que implementan? ¿Cuándo comparar usando getClass() y cuándo getClass().getName()? ¿Hay alguna diferencia entre estos enfoques para comparar dos tipos de clases de objetos (nombres)?Comparación de dos clases por sus tipos o nombres de clase

public abstract class Monster { ... } 
public class MonsterTypeOne extends Monster { ... } 
public class MonsterTypeTwo extends Monster { ... } 

    Monster monster = MonsterTypeOne(); 
    Monster nextMonster = MonsterTypeTwo(); 


if(nextMonster.getClass().getName().equals(monster.getClass().getName()))// #1 

if(nextMonster.getClass().equals(monster.getClass()))// #2 

EDITAR 1


¿Qué hay de:?

nextMonster.getClass().equals(MonsterTypeOne.class) 
+0

¿Necesita .equals con getClass? La clase devuelve un objeto que no es de Cadena, creo. +1 pregunta interesante. – jmort253

Respuesta

18

¿Hay alguna diferencia entre este se acerca a comparar los dos tipos de clases de objetos (nombres)?

Sí. Dos clases pueden tener el mismo nombre si están cargadas por diferentes ClassLoader s.

"The basics of Java class loaders" dice

En su forma más simple, un cargador de clases crea un espacio de nombre plano de los cuerpos de clases que se hace referencia mediante un nombre de cadena.

"Eclipse - a tale of two VMs (and many classloaders)" dice

Eso significa que es posible tener dos clases con el mismo nombre cargado en una máquina virtual a la vez, siempre que cuenten con dos cargadores de clases separadas


¿Cuándo comparar usando getClass() y cuándo getClass().getName()?

Si quieres saber si dos objetos son del mismo tipo que debe utilizar el método equals para comparar las dos clases - la primera opción.

No puedo imaginar por qué querrías hacer esto, pero si quieres saber si dos objetos con diferentes tipos de concreto tienen tipos con el mismo nombre completo, entonces podrías usar el segundo. Si no entiende "tipos concretos" y "nombres completamente calificados" en el contexto de Java, entonces no está escribiendo código de análisis de tipo para Java, por lo que no desea hacerlo.

28

Uso class.equals():

if (nextMonster.getClass().equals(monster.getClass())) 

o, debido a que cada clase es como un producto único - sólo hay una instancia de cada clase por JVM - incluso se puede utilizar una comparación de identidad:

if (nextMonster.getClass() == monster.getClass()) 
3

I se encontró con un problema al comparar dos clases usando .equals. La solución proporcionada anteriormente no es del todo precisa. La clase no implementa Comparable.

Las referencias de clase no son necesariamente verdaderas únicas dentro de una JVM porque puede tener múltiples ClassLoaders.

Estaba escribiendo un plugin de Maven que estaba sacando anotaciones de los beans después de la compilación. El complemento tenía un cargador de clases y yo tenía mi propio cargador de clases. Al comparar dos clases del mismo nombre de diferentes cargadores, la comparación fallaría.

La implementación de Object.equals se parece a esto:

public boolean More ...equals(Object obj) { 
     return (this == obj); 
} 

referencias Entonces se le comparando.

Si está comparando las clases y que sepa con certeza no sólo será un cargador de clases involucrado se puede utilizar con seguridad .equals o c2 c1 == pero si no está seguro de que debe comparar por su nombre:

if(c1.getName().equals(c2.getName()) { 
    ... 
} 
+0

¿por qué necesitarías comparar nombres de clase de dos cargadores de clases diferentes? ¿Es eso un senario válido? Dame un ejemplo cuando necesites hacer eso en la vida real. –

+0

Mi aplicación fue muy inusual. Estaba creando un complemento Maven que genera documentación para los puntos finales REST. Quería usar las anotaciones JAX (o Spring) para generar documentos HTML. El complemento Maven utilizado cargaría todas las clases con la clase JarClassLoader y el complemento Maven ejecutó su código en el cargador de clases de la compilación. Estaba tratando de ver si la anotación estaba presente en la clase Jar pero la comparación falló a pesar de que eran los mismos nombres de clase. Terminé abandonando el proyecto. –

1

De hecho, comparar la clase de confianza por su nombre es una debilidad. Consulte https://cwe.mitre.org/data/definitions/486.html

if (nextMonster.getClass() == monster.getClass()) 

es la forma correcta de comparar clases

if (nextMonster.getClass().equals(monster.getClass())) 

debería funcionar por la misma razón mencionada @Bohemian

0

Otra forma de lograr el mismo estará reemplazando código hash en subclase.

public interface Parent { 
} 

public static class Child1 implements Parent{ 
    private String anyfield="child1"; 

    @Override 
    public int hashCode() { 
     //Code based on "anyfield" 
    } 

    @Override 
    public boolean equals(Object obj) { 
     //equals based on "anyfield" 
    } 
} 

public static class Child2 implements Parent{ 
    private String anyfield="child2"; 

    @Override 
    public int hashCode() { 
     //Code based on "anyfield" 
    } 

    @Override 
    public boolean equals(Object obj) { 
     //equals based on "anyfield" 
    } 
} 

Ahora los iguales volverá si implementaciones/subclases son del mismo tipo de hormigón.

public static void main(String args[]){ 
    Parent p1=new Child1(); 
    Parent p2=new Child1(); 
    Parent p3=new Child2(); 
    System.out.println("p1 and p2 are same : "+p1.equals(p2)); 
    System.out.println("p2 and p3 are same : "+p2.equals(p3)); 
} 

Salida-

p1 and p2 are same : true 
p2 and p3 are same : false 
Cuestiones relacionadas