Resumen de algunos detalles de la clase Java String

valueEste artículo presenta principalmente las variables miembro y intern()los métodos de la clase String ==y equals()sus diferencias.

valueVariables miembro

Antes de presentar esta variable miembro, me gustaría hablar sobre por qué Java presenta el concepto de grupo constante.

Queremos decir que cada vez que creamos una cadena, necesitamos asignar un espacio de memoria. Si incluimos cadenas con el mismo contenido en diferentes lugares del programa, se desperdiciará memoria. En este momento, naturalmente esperamos crear una cadena cada vez Guárdelos todos, y si necesita la misma cadena en el futuro, simplemente reutilice la referencia de la cadena guardada. Con todo, el propósito del grupo de constantes es ahorrar memoria.

Luego valuese usa para hacer esto y almacena el contenido contenido en la cadena. Al crear un objeto String, la referencia literal pasada se usa como valuevalor.

Este valor literal primero se buscará en el pool de constantes, y si lo encuentra, devolverá la referencia de la cadena correspondiente al pool de constantes, si no lo encuentra, creará una nueva cadena en el pool de constantes y devolverá su referencia.

Pero valueno siempre es una referencia a una cadena en el conjunto de constantes, como:

String str = new String("ab") + new String("c");

strEl valor almacenado del objeto valueno será el valor de la cadena en el conjunto de constantes, porque esta es la suma de dos variables y no se puede determinar de forma única en el momento de la compilación . En cuanto a por qué es imposible determinarlo al compilar, consulte el siguiente ejemplo:

public class MyTest {
    
    
    static final String a = "ab";
    static final String b = "c";
    public static void main(String[] args) {
    
    
        String c = a + b;
        System.out.println(c == "abc");
    }
}

Este código generará true, si finalse elimina, se convertirá en false. En realidad, esto muestra que si se puede determinar de forma única en el momento de la compilación, el compilador realizará las optimizaciones correspondientes durante el proceso de compilación en un archivo .class.

De hecho, no solo se optimizará la situación anterior, sino también la adición de constantes de cadena:

String str= "ab" + "cd" + "ef";

se convertirá

String str= "abcdef";

Para la adición de variables de cadena:

String str = "abcdef"; 

for(int i=0; i<1000; i++) {
    
     
  str = str + i; 
} 

se convertirá

String str = "abcdef"; 

for(int i=0; i<1000; i++) {
    
     
  str = (new StringBuilder(String.valueOf(str))).append(i).toString(); 
} 

Además de lo anterior, de hecho, las constantes de cadena literales que escribimos cuando escribimos código, por ejemplo "abc", se optimizarán en un objeto String durante la compilación. Específicamente, si varias constantes de cadena literal tienen el mismo valor, el compilador las fusionará en el mismo objeto de cadena y generará las referencias constantes correspondientes en el conjunto de constantes de la clase.

intern()método

El método antes y después de JDK7 intern()es diferente en la implementación subyacente.Este método se utiliza para devolver la referencia de la cadena en el conjunto de constantes.

intern()Firma del método:public native String intern()();

Antes de JDK7

Al crear un objeto de cadena a través del constructor de cadenas, intern()el método primero verificará si hay una constante de cadena correspondiente en el grupo de constantes; de lo contrario, copiará una copia en el grupo de constantes y luego devolverá la referencia a la cadena copiada en la constante. piscina

Después de JDK7

Si no está en el grupo de constantes, solo se registrará la referencia del objeto String en el grupo de constantes y no se copiará ninguna constante de cadena en el grupo de constantes.

Enlace de referencia: de java.lang.String#intern, la diferencia entre el conjunto de constantes de cadena antes de JDK6 y JDK7 y después

#La diferencia ==con equals()el método
Con la base anterior, será mucho más fácil entender la diferencia entre los dos.

Para tipos complejos de datos, ==en realidad está comparando los códigos hash de los dos.

La generación de código hash predeterminado parece estar basada en la dirección de memoria del objeto.

Entonces new String("abc")y "abc"no son iguales, porque básicamente no son el mismo objeto , pero obviamente generalmente pensamos que siempre que el contenido de la cadena sea el mismo, es el mismo objeto, por lo que en este momento, equals()el método debe reescribirse para determinar si son iguales, pero este requisito se debe a demasiado común, Java ya lo ha hecho por nosotros: reescribir equals()métodos.

Esta es en realidad la pregunta anticuada: por qué reescribir hashCode()el método debe reescribir el equals()método.

Esto se debe a que hashCode()después de reescribir el método, las API, como las colecciones, juzgarán si los objetos son iguales en función de esto, pero sabemos que las funciones hash siempre colisionan inevitablemente , por lo que diferentes objetos también pueden tener códigos hash calculados que son iguales. Si no anulamos equals()el método, básicamente habrá problemas al 100%.

Debido a que el equals()método predeterminado es juzgar si dos objetos son iguales de acuerdo con la dirección de memoria, entonces no deben ser iguales, porque pensamos Person p1 = new Person("小明");y Person p2 = new Person("小明");somos el mismo objeto, incluso si en realidad creamos dos objetos.

Supongo que te gusta

Origin blog.csdn.net/weixin_55658418/article/details/130452547
Recomendado
Clasificación