tipos relacionales programacion precedencia operadores logicos ejemplos datos condicionales comparacion java equals

relacionales - precedencia de operadores java



Cómo anular el método de igualdad en Java (9)

Punto 10: Obedece el contrato general cuando prevalece el igual

De acuerdo con Effective Java , Anular el método equals parece simple, pero hay muchas maneras de equivocarse, y las consecuencias pueden ser nefastas. La forma más fácil de evitar problemas no es anular el método de equals , en cuyo caso cada instancia de la clase es igual a sí misma. Esto es lo correcto si se cumple alguna de las siguientes condiciones:

  • Cada instancia de la clase es inherentemente única . Esto es cierto para clases como Thread que representan entidades activas en lugar de valores. La implementación equals proporcionada por Object tiene exactamente el comportamiento correcto para estas clases.

  • No es necesario que la clase proporcione una prueba de "igualdad lógica". Por ejemplo, java.util.regex.Pattern podría haber reemplazado a igual para comprobar si dos instancias de patrón representaban exactamente la misma expresión regular, pero los diseñadores no pensaban que los clientes necesitarían o querrían esta funcionalidad. Bajo estas circunstancias, la implementación igual heredada de Object es ideal.

  • Una superclase ya ha anulado iguales, y el comportamiento de la superclase es apropiado para esta clase. Por ejemplo, la mayoría de las implementaciones de Set heredan su implementación equals de AbstractSet, las implementaciones de listas de AbstractList y las implementaciones de Map de AbstractMap.

  • La clase es privada o privada del paquete , y está seguro de que su método igual nunca se invocará. Si eres extremadamente reacio al riesgo, puedes anular el método equals para asegurarte de que no se invoca accidentalmente:

El método equals implementa una relación de equivalencia. Tiene estas propiedades:

  • Reflexivo: Para cualquier valor de referencia no nulo x , x.equals(x) debe devolver verdadero.

  • Simétrico: Para cualquier valor de referencia no nulo x e y , x.equals(y) debe devolver verdadero si y solo si y.equals (x) devuelve verdadero.

  • Transitivo: Para cualquier valor de referencia no nulo x , y , z , si x.equals(y) devuelve true y y.equals(z) devuelve true , entonces x.equals(z) debe devolver true .

  • Constante: para cualquier valor de referencia no nulo y , las invocaciones múltiples de x.equals(y) deben devolver de forma consistente true o devolverse de manera consistente false , siempre que no se modifique la información utilizada en comparaciones iguales.

  • Para cualquier valor de referencia no nulo x , x.equals(null) debe devolver false .

Aquí hay una receta para un método de igual calidad de alta calidad:

  1. Use el operador == para verificar si el argumento es una referencia a este objeto. Si es así, devuelve verdadero. Esta es solo una optimización del rendimiento, pero una que vale la pena si la comparación es potencialmente costosa.

  2. Use el operador instanceof para verificar si el argumento tiene el tipo correcto. Si no, devuelve falso. Normalmente, el tipo correcto es la clase en la que se produce el método. Ocasionalmente, es una interfaz implementada por esta clase. Use una interfaz si la clase implementa una interfaz que refine el contrato igual para permitir comparaciones entre las clases que implementan la interfaz. Las interfaces de colección como Set, List, Map y Map.Entry tienen esta propiedad.

  3. Echa el argumento al tipo correcto. Debido a que este elenco fue precedido por una instancia de prueba, se garantiza que tendrá éxito.

  4. Para cada campo "significativo" en la clase, verifique si ese campo del argumento coincide con el campo correspondiente de este objeto. Si todas estas pruebas tienen éxito, devuelve verdadero; de lo contrario, devuelve falso. Si el tipo en el Paso 2 es una interfaz, debe acceder a los campos del argumento a través de métodos de interfaz; si el tipo es una clase, puede acceder a los campos directamente, dependiendo de su accesibilidad.

  5. Para los campos primitivos cuyo tipo no es float o double , use el operador == para las comparaciones; para los campos de referencia del objeto, llame al método equals recursivamente; para los campos float , use el Float.compare(float, float) estático Float.compare(float, float) ; y para campos double , use Double.compare(double, double) . El tratamiento especial de los campos flotantes y dobles se hace necesario por la existencia de Float.NaN , -0.0f y los valores dobles análogos; Si bien puede comparar float y campos double con los métodos estáticos Float.equals y Double.equals , esto implicaría el autoboxing en cada comparación, lo que tendría un rendimiento deficiente. Para los campos de array , aplique estas pautas a cada elemento. Si cada elemento en un campo de matriz es significativo, use uno de los métodos Arrays.equals .

  6. Algunos campos de referencia de objeto pueden contener legítimamente null . Para evitar la posibilidad de una NullPointerException , verifique esos campos para la igualdad utilizando el método estático Objects.equals(Object, Object) .

    // Class with a typical equals method public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber(int areaCode, int prefix, int lineNum) { this.areaCode = rangeCheck(areaCode, 999, "area code"); this.prefix = rangeCheck(prefix, 999, "prefix"); this.lineNum = rangeCheck(lineNum, 9999, "line num"); } private static short rangeCheck(int val, int max, String arg) { if (val < 0 || val > max) throw new IllegalArgumentException(arg + ": " + val); return (short) val; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof PhoneNumber)) return false; PhoneNumber pn = (PhoneNumber)o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } ... // Remainder omitted }

Estoy intentando anular el método de igualdad en Java. Tengo una clase People que básicamente tiene 2 campos de datos nombre y edad. Ahora quiero anular el método de igual para poder verificar entre dos objetos de personas.

Mi código es el siguiente

public boolean equals(People other){ boolean result; if((other == null) || (getClass() != other.getClass())){ result = false; } // end if else{ People otherPeople = (People)other; result = name.equals(other.name) && age.equals(other.age); } // end else return result; } // end equals

Pero cuando escribo age.equals (other.age) me da error ya que el método equals solo puede comparar String y age es Integer.

Por favor ayúdame a arreglar esto.

Gracias es Advance.

Utilicé el operador == como se sugirió y mi problema está resuelto. Muchas gracias a todos por hacer un esfuerzo para ayudarme.


Al comparar objetos en Java, realiza una comprobación semántica , comparando el tipo y el estado de identificación de los objetos a:

  • sí mismo (misma instancia)
  • sí mismo (clonar, o copia reconstruida)
  • otros objetos de diferentes tipos
  • otros objetos del mismo tipo
  • null

Reglas:

  • Simetría : a.equals(b) == b.equals(a)
  • equals() siempre arroja true o false , pero nunca una NullpointerException , ClassCastException o cualquier otra throwable

Comparación:

  • Verificación de tipo : ambas instancias deben ser del mismo tipo, lo que significa que debe comparar las clases reales para la igualdad. Esto a menudo no se implementa correctamente, cuando los desarrolladores usan instanceof para la comparación de tipos (que solo funciona mientras no haya subclases, y viola la regla de simetría cuando A extends B -> a instanceof b != b instanceof a) .
  • Comprobación semántica del estado de identificación : asegúrese de comprender por qué estado se identifican las instancias. Las personas pueden ser identificadas por su número de seguro social, pero no por el color del pelo (puede teñirse), el nombre (puede cambiarse) o la edad (cambia todo el tiempo). Solo con objetos de valor debe comparar el estado completo (todos los campos no transitorios); de lo contrario, verifique solo lo que identifica a la instancia.

Para su clase de Person :

public boolean equals(Object obj) { // same instance if (obj == this) { return true; } // null if (obj == null) { return false; } // type if (!getClass().equals(obj.getClass())) { return false; } // cast and compare state Person other = (Person) obj; return Objects.equals(name, other.name) && Objects.equals(age, other.age); }

Clase de utilidad genérica reutilizable:

public final class Equals { private Equals() { // private constructor, no instances allowed } /** * Convenience equals implementation, does the object equality, null and type checking, and comparison of the identifying state * * @param instance object instance (where the equals() is implemented) * @param other other instance to compare to * @param stateAccessors stateAccessors for state to compare, optional * @param <T> instance type * @return true when equals, false otherwise */ public static <T> boolean as(T instance, Object other, Function<? super T, Object>... stateAccessors) { if (instance == null) { return other == null; } if (instance == other) { return true; } if (other == null) { return false; } if (!instance.getClass().equals(other.getClass())) { return false; } if (stateAccessors == null) { return true; } return Stream.of(stateAccessors).allMatch(s -> Objects.equals(s.apply(instance), s.apply((T) other))); } }

Para su clase Person , usando esta clase de utilidad:

public boolean equals(Object obj) { return Equals.as(this, obj, t -> t.name, t -> t.age); }


Como supongo que la age es de tipo int :

public boolean equals(Object other){ boolean result; if((other == null) || (getClass() != other.getClass())){ result = false; } // end if else{ People otherPeople = (People)other; result = name.equals(otherPeople.name) && age == otherPeople.age; } // end else return result; } // end equals


El método equals define un parámetro de método de tipo Object y su tipo de retorno es booleano.

Don’t change the name of the method, its return type, or the type of method parameter

cuando defines ( anula ) este método en tu clase para comparar dos objetos.

public boolean equals(Object anObject) { ... }


En primer lugar: no está anulando equals , lo está sobrecargando .

Sin ver la declaración de age real, es difícil decir por qué está recibiendo el error.


No estoy seguro de los detalles ya que no ha publicado todo el código, pero:

  • recuerde anular hashCode() también
  • el método equals debería tener Object , no People como su tipo de argumento. En este momento está sobrecargando, sin anular, el método equals, que probablemente no es lo que quiere, especialmente dado que revisa su tipo más tarde.
  • puede usar instanceof para verificar que se trata de un objeto People, por ejemplo if (!(other instanceof People)) { result = false;}
  • equals se usa para todos los objetos, pero no para primitivos. Creo que quieres decir que la edad es un int (primitivo), en cuyo caso simplemente usa == . Tenga en cuenta que un Entero (con una "I" mayúscula) es un Objeto que debe ser comparado con iguales.

Consulte ¿Qué problemas se deben tener en cuenta al anular equals y hashCode en Java? para más detalles.


si la edad es int, debe usar == si es un objeto Integer, entonces puede usar equals (). También debe implementar el método de código hash si anula los iguales. Los detalles del contrato están disponibles en el javadoc de Object y también en varias páginas en la web.


//Written by K@ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here ArrayList<Person> people = new ArrayList<Person>(); people.add(new Person("Subash Adhikari",28)); people.add(new Person("K",28)); people.add(new Person("",4)); people.add(new Person("Subash Adhikari",28)); for (int i=0;i<people.size()-1;i++){ for (int y=i+1;y<=people.size()-1;y++){ System.out.println("-- " + people.get(i).getName() + " - VS - " + people.get(y).getName()); boolean check = people.get(i).equals(people.get(y)); System.out.println(check); } } } } //written by K@ public class Person { private String name; private int age; public Person(String name, int age){ this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (!Person.class.isAssignableFrom(obj.getClass())) { return false; } final Person other = (Person) obj; if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { return false; } if (this.age != other.age) { return false; } return true; } @Override public int hashCode() { int hash = 3; hash = 53 * hash + (this.name != null ? this.name.hashCode() : 0); hash = 53 * hash + this.age; return hash; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

Salida:

correr:

- Subash Adhikari - VS - K falso

- Subash Adhikari - VS - falso

- Subash Adhikari - VS - Subash Adhikari cierto

- K - VS - falso

- K - VS - Subash Adhikari falso

- - VS - Subash Adhikari falso

- CONSTRUIR ÉXITO (tiempo total: 0 segundos)


@Override public boolean equals(Object that){ if(this == that) return true;//if both of them points the same address in memory if(!(that instanceof People)) return false; // if "that" is not a People or a childclass People thatPeople = (People)that; // than we can cast it to People safely return this.name.equals(thatPeople.name) && this.age == thatPeople.age;// if they have the same name and same age, then the 2 objects are equal unless they''re pointing to different memory adresses }