Reconocer la clase String (problemas relacionados con el diseño de cadenas y memoria (1))

1. Crea una cadena

Formas comunes de construir String

// 方式一
String str = "Hello Bit";
// 方式二
String str2 = new String("Hello Bit");
// 方式三
char[] array = {
    
    'a', 'b', 'c'};
String str3 = new String(array);

En el documento oficial ( https://docs.oracle.com/javase/8/doc/api/index.html ) podemos ver que String también soporta muchos otros métodos de construcción, podemos comprobarlo cuando lo usamos.

Precauciones:

  • Las constantes de cadena literal como "hola" también son Cadena.
  • La cadena es un tipo de referencia . String str ="Hello";

El diseño de la memoria de códigos es el siguiente:

Recuerdos "cita"

  • Las referencias son similares a los punteros en lenguaje C, excepto que se abre un pequeño espacio de memoria en la pila para almacenar una dirección.Sin embargo, las referencias y los punteros no son lo mismo, los punteros pueden realizar varias operaciones numéricas (puntero + 1), etc. pero no se pueden hacer referencias, este es un tipo de puntero "no tan flexible".
  • Además, también puede pensar en una referencia como una etiqueta, que se "publica" en un objeto. Un objeto se puede colocar con una etiqueta o varias. Si un objeto no tiene una etiqueta, entonces el objeto será tratada como basura por la JVM El objeto se recicla.
  • Las matrices, cadenas y clases personalizadas en Java son todos tipos de referencia.

Dado que String es un tipo de referencia, para el siguiente código

String str1 = "Hello";
String str2 = str1;

El diseño de la memoria se muestra en la figura:
Inserte la descripción de la imagen aquí¿Se modificarán str1 y str2 en consecuencia?

String str1 = "Hello";
String str2 = str1;
str1 = "world";
System.out.println(str2);
// 执行结果
Hello

Descubrimos que después de "modificar" str1, str2 no cambió, ¿o es hola?
De hecho, el código como str1 = "world" no es una cadena "modificada", pero hace que la referencia de str1 apunte a un nuevo objeto String .

Diagrama de disposición de la memoria:
Inserte la descripción de la imagen aquí

2. La comparación de cadenas es igual

Si hay dos variables de tipo int, puede usar == para completar el juicio de su igualdad.

int x = 10 ;
int y = 10 ;
System.out.println(x == y); 
// 执行结果
true

¿Si dices que == se usa ahora en objetos Stringg?

代码1
String str1 = "Hello";
String str2 = "Hello"; 
System.out.println(str1 == str2); 
// 执行结果
true

Parece que no hay problema, pruebe con otro código y descubra que la situación no es muy buena

代码2
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);
// 执行结果
false

Analice la diferencia entre las dos formas de crear String.

Código de Diseño de memoria 1:
Inserte la descripción de la imagen aquí Nos encontramos, str1 y el punto str2 al mismo objeto es el tiempo como "Hola" es una constante de cadena tales. Una cadena constante piscina de.

Con respecto al grupo de constantes de cadena: las constantes literales de cadena
como "Hola" también requieren una cierta cantidad de espacio de memoria para almacenar. Estas constantes tienen una característica que no necesitan ser modificadas (constantes). Por lo tanto, si hay demasiadas en el código Si necesita usar "Hola" en todas las referencias, puede referirse directamente a esta ubicación en el grupo constante, y no es necesario almacenar "Hola" en la memoria dos veces.

Disposición de la memoria del código 2:
Inserte la descripción de la imagen aquí

Por String str1 = new String("Hello");String objetos creados de tal manera equivalente al montón y luego abrieron espacio adicional para almacenar el contenido de "Hola", es decir, existe la memoria de dos "Hola".

La comparación String == no es comparar el contenido de la cadena, sino comparar si dos referencias apuntan al mismo objeto.

Acerca de la comparación
de objetos En los lenguajes de programación orientados a objetos, hay tres formas diferentes de comparar objetos, comparar identidades, comparar valores y comparar tipos. En la mayoría de los lenguajes de programación, == se usa para comparar y comparar valores. Pero en Java El == se usa para comparar identidades.
¿Cómo entender el valor de comparación y comparar identidades? Puede
imaginar una escena en la que puede recoger un envío urgente y hay casilleros de paquetes. Hay muchas cuadrículas en él. Hay cosas en cada cuadrícula .

Si desea comparar el contenido de cadenas en Java, debe utilizar el método equals proporcionado por la clase String.

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1.equals(str2));
// System.out.println(str2.equals(str1)); // 或者这样写也行
// 执行结果
true

Notas sobre el uso de equals
Ahora tenemos que comparar si las dos cadenas str y "Hello" son iguales, ¿cómo lo escribimos?

String str = new String("Hello");
// 方式一
System.out.println(str.equals("Hello"));
// 方式二
System.out.println("Hello".equals(str));

Es más recomendable utilizar el "Método Dos". Una vez que str sea nulo, el código del Método Uno arrojará una excepción, pero el Método Dos no.

String str = null;
// 方式一
System.out.println(str.equals("Hello"));  // 执行结果抛出java.lang.NullPointerException异常
// 方式二
System.out.println("Hello".equals(str)); //执行结果 false

Nota: una constante literal como "Hola" es esencialmente un objeto String, y puede usar equals y otros métodos de objeto String.

3. Pool de constantes de cadena

En el ejemplo anterior, hay dos operaciones de instanciación de la clase String, asignación directa y una nueva cadena nueva.
1. Asignación directa

String str1 = "hello" ;
String str2 = "hello" ; 
String str3 = "hello" ; 
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // true
System.out.println(str2 == str3);   //true

Inserte la descripción de la imagen aquí¿Por qué no se ha abierto ahora un nuevo espacio de memoria dinámica?

El diseño de la clase String utiliza un patrón de diseño compartido

De hecho, un grupo de objetos (grupo constante de cadenas) se mantiene automáticamente en la parte inferior de la JVM

  • Si ahora se usa el modo de asignación directa para crear una instancia de un objeto de la clase String, el objeto instanciado (contenido de la cadena) se guardará automáticamente en este grupo de objetos.
  • Si continúa utilizando el modo de asignación directa para declarar el objeto de clase String la próxima vez, si hay contenido especificado en el grupo de objetos en este momento, se hará referencia a él directamente.
  • De lo contrario, abra un nuevo objeto de cadena y guárdelo en el grupo de objetos para el próximo uso

Entendiendo "piscina" (piscina)

  • El "grupo" es una forma común e importante de mejorar la eficiencia en la programación. Encontraremos varios "grupos de memoria", "grupos de subprocesos", "grupos de conexiones de bases de datos" en nuestro aprendizaje futuro ...
  • Sin embargo, el concepto de Chi no es exclusivo de las computadoras, sino que proviene de la vida. Por ejemplo, en
    la vida real, hay una diosa llamada "té verde". Mientras habla de objetos con Gao Fushuai, también puede interactuar con otros pollas. Ambiguo. En este momento, este diaosi se llama "llanta de refacción". Entonces, ¿por qué tener una llanta de refacción? Porque una vez que rompes con Gao Fushuai, puedes encontrar una llanta de refacción de inmediato, lo cual es más eficiente .
  • Si esta diosa es ambigua con muchas pollas al mismo tiempo, entonces estas llantas de repuesto se llaman piscinas de llantas de repuesto.

2. Usando el método de construcción Es
una práctica estándar crear instancias de objetos de clase usando el método de construcción. Analice los siguientes procedimientos:

String str = new String("hello");

Inserte la descripción de la imagen aquíEste enfoque tiene dos desventajas:

  1. Si se utiliza el método de construcción de cadena, se abrirán dos espacios de memoria de pila y uno de los espacios de memoria de pila se convertirá en espacio de basura (la constante de cadena "hola" también es un objeto anónimo, después de que se usa una vez, no se utilizará durante más tiempo y se convertirá en un espacio de basura. La JVM lo reciclará automáticamente).
  2. Problema de uso compartido de cadenas: la misma cadena puede almacenarse varias veces, lo que supone una pérdida de espacio.

Podemos usar el método interno de String para agregar manualmente objetos String al grupo de constantes de cadena

// 该字符串常量并没有保存在对象池之中
String str1 = new String("hello") ; 
String str2 = "hello" ; 
System.out.println(str1 == str2);
// 执行结果
false

String str1 = new String("hello").intern() ;
String str2 = "hello" ; 
System.out.println(str1 == str2);
// 执行结果
true

Inserte la descripción de la imagen aquíPregunta de la entrevista: explique la diferencia entre la instanciación de los dos tipos de objetos en la clase String

  1. Asignación directa: solo se abrirá una parte del espacio de memoria del montón y el objeto de cadena se puede guardar automáticamente en el grupo de objetos para el próximo uso.
  2. Método de construcción: Se abrirán dos espacios de memoria del montón y no se guardarán automáticamente en el grupo de objetos. Puede usar el método intern () para ingresar manualmente al grupo.

Por lo tanto, generalmente usamos la asignación directa para crear objetos String.

Supongo que te gusta

Origin blog.csdn.net/qq_47364122/article/details/112968111
Recomendado
Clasificación