[Corte constantemente, la razón sigue siendo desordenada] Esas cosas sobre iguales y == en Java

Elaborar sobre iguales y ==

1. Originado a partir de Objeto

Todos sabemos que todas las clases en Java heredan la superclase Object por defecto, y Object tiene más de 10 métodos, aquí presentamos los principales y toStringmétodos .equalshashcode

  • toStingEl método devuelve " " de forma predeterminada 类名@地址值; generalmente lo reescribimos y luego podemos imprimir directamente el objeto para obtener la forma reescrita de la salida.

Los siguientes puntos destacados equalsy hashcode:

  • equalsEl método compara el objeto (dirección) por defecto, es decir, se realiza la operación ==. Si el contenido necesita ser comparado, necesita ser reescrito.
  • hashcodeEl valor predeterminado es devolver una cadena de enteros basada en la dirección del objeto, lo que significa que la misma dirección hashcodees la misma. Y hashcodees un método en Object, un nativemétodo local, lo que indica que el método se implementa llamando a otros lenguajes, que es un poco como una interfaz, y no necesita implementarlo usted mismo.

El siguiente es el código fuente relevante en la clase Object:

 public String toString() {
    
    
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
public boolean equals(Object obj) {
    
    
        return (this == obj);
    }
public native int hashCode();

2, enredado en cuerda

Hablemos de las características java.lang.Stringde la neutralización :equalshashcode

String equalsy hashcodeambos se reescriben.

En primer lugar, el código hash calcula el hash de acuerdo con el contenido del objeto, por lo que el contenido del objeto es el mismo y su código hash es el mismo.

public int hashCode() {
    
    
        int h = hash;
        if (h == 0 && value.length > 0) {
    
    
            char val[] = value;
			
            //这种 hash 计算方式不难看出,元素 value 相同 h 会是一样的
            for (int i = 0; i < value.length; i++) {
    
    
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

Para cadenas, equals compara el contenido del objeto, lo que también se debe a la especificidad de las cadenas.

Entonces == compara la dirección del objeto.

public boolean equals(Object anObject) {
    
    
    //对象相同,直接相同
        if (this == anObject) {
    
    
            return true;
        }
    //类型相同且每个元素值相同,认为相同
        if (anObject instanceof String) {
    
    
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
    
    
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
    
    
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

3. Verificación de código

Aquí está el código de prueba:

public class TEST {
    
    
    public static void main(String[] args){
    
    

        Object o1 = new Object();
        Object o2 = new Object();
        Object o3 = o2;
        System.out.println(o1==o2); //false
        System.out.println(o1.equals(o2)); //false,Object 原生 equals,默认比较地址
        System.out.println(o1.hashCode()==o2.hashCode()); //false,根据地址计算 hash
        System.out.println(o2.hashCode()==o3.hashCode()); //true

        String s1 = "abc";
        String s2 = s1; //常量池优化机制
        String s3 = new String("abc");
        System.out.println(s1==s3); //false 地址不一样,一个在常量池中一个在堆中
        System.out.println(s1.equals(s3)); //true,比较内容
        System.out.println(s2.hashCode()==s1.hashCode()); //true,根据内容计算 hash
        System.out.println(s1.hashCode()==s3.hashCode()); //true
    }

}

4. Método de anulación

En algunos escenarios, necesitamos personalizar la regla "igual". Por ejemplo, si definimos el mismo contenido del objeto como igual, debemos anular el método de igualdad:

import java.util.Objects;

public class Person {
    
    	
	private String name;
	private int age;
	
    @Override
    public boolean equals(Object o) {
    
    
        // 如果对象地址一样,则认为相同
        if (this == o)
            return true;
        // 如果参数为空,或者类型信息不一样,则认为不同
        if (o == null || getClass() != o.getClass())
            return false;
        // 转换为当前类型
        Person person = (Person) o;
        // 要求基本类型相等,并且将引用类型交给 java.util.Objects 类的 equals 静态方法取用结果
        return age == person.age && Objects.equals(name, person.name);
    }
}
 //对象比较地址,字符串比较内容
 public static boolean equals(Object a, Object b) {
    
    
 //1,对象类型时
 //a==b 为 true,则 true
 //a==b 为 false,则 false;
 //2,string 类型时
 //地址 true,内容 true,则 true
 //地址 false,内容 true,则 true;地址不等内容不等,flase
        return (a == b) || (a != null && a.equals(b));
    }

En algunas ocasiones, también necesitamos reescribir el código hash. Por ejemplo, el mecanismo de juicio de "igualdad de elementos" en HashSet es considerar exhaustivamente los métodos hashcode y equals, por lo que cuando personalizamos el objeto, debemos reescribir el código hash y equals. métodos.

La reescritura del método de equals se refiere al ejemplo anterior. La siguiente es la reescritura del método hashcode y el código fuente del método correspondiente:

@Override 
public int hashCode() {
    
    
     //仍然调用的是 Objects 的 hash 方法
    //对于这里而言,age 走地址判断;name 走内容判断;所以只要他们内容相同就会返回相同的 hash
        return Objects.hash(name, age);
    }
public static int hash(Object... values) {
    
    
        return Arrays.hashCode(values);
    }
public static int hashCode(Object a[]) {
    
    
        if (a == null)
            return 0;

        int result = 1;
		//仍然走的是 Object 的 hashCode 方法
        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }

Por supuesto, el método de reescritura anterior, la generación de ideas, proporciona una plantilla de reescritura, que se puede generar con un solo clic.

5. Resumen

El código hash de Object devuelve el valor según la dirección, equals compara la dirección, == compara la dirección;

El código hash de String devuelve el valor según el contenido, equals compara el contenido, == compara la dirección.

Es decir, Object siempre compara la dirección. Debido a que String tiene un método de reescritura, es el contenido de la comparación. == es en realidad una dirección de comparación en sí misma.

Supongo que te gusta

Origin blog.csdn.net/qq_40589204/article/details/119394186
Recomendado
Clasificación