java - una - Comparando dos clases por sus tipos o nombres de clase
obtener el nombre de una variable en java (5)
¿Hay alguna diferencia entre estos enfoques para comparar dos tipos de clases de Objetos (nombres)?
Sí. Dos clases pueden tener el mismo nombre si son cargadas por diferentes ClassLoader
s.
"Los conceptos básicos de los cargadores de clases Java" dice
En su forma más simple, un cargador de clases crea un espacio de nombre plano de cuerpos de clase a los que se hace referencia mediante un nombre de cadena.
"Eclipse: un cuento de dos máquinas virtuales (y muchos cargadores de clases)" dice
Eso significa que es posible tener dos clases con el mismo nombre cargado en una máquina virtual a la vez, siempre que tengan dos ClassLoaders separados
¿Cuándo comparar utilizando
getClass()
y cuándogetClass().getName()
?
Si desea saber si dos objetos son del mismo tipo, debe usar el método de equals
para comparar las dos clases: la primera opción.
No puedo imaginar por qué querría hacer esto, pero si quiere saber si dos objetos con diferentes tipos concretos tienen tipos con el mismo nombre completo, entonces puede usar el segundo. Si no entiende los "tipos concretos" y los "nombres completamente calificados" en el contexto de Java, entonces no está escribiendo el código de análisis de tipo para java, por lo que no desea hacerlo.
¿Hay necesidad de comparar dos objetos basados en la clase que implementan? ¿Cuándo comparar utilizando getClass()
y cuándo getClass().getName()
? ¿Hay alguna diferencia entre estos enfoques para comparar dos tipos de clases de Objetos (nombres)?
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é pasa: ?
nextMonster.getClass().equals(MonsterTypeOne.class)
De hecho, comparar una clase confiable por 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()))
Todavía debería funcionar por la misma razón que mencionó @Bohemian
Me encontré con un problema comparando 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 singletons verdaderos dentro de una JVM porque puede tener múltiples ClassLoaders.
Estaba escribiendo un plugin de Maven que estaba extrayendo anotaciones de beans después de compilar. 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 ve así:
public boolean More ...equals(Object obj) {
return (this == obj);
}
Así que estarás comparando referencias.
Si está comparando clases y sabe con seguridad que solo habrá un cargador de clases involucrado que puede usar con seguridad .equals o c1 == c2, pero si no está seguro, debe comparar por nombre:
if(c1.getName().equals(c2.getName()) {
...
}
Otra forma de lograr lo mismo será anular el código hash en la 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án si las implementaciones / subclases son del mismo tipo concreto.
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
Utilice class.equals()
:
if (nextMonster.getClass().equals(monster.getClass()))
o, porque cada clase es como un singleton, solo hay una instancia de cada clase por JVM, incluso puede usar una comparación de identidad:
if (nextMonster.getClass() == monster.getClass())