Cadenas y grupos de constantes de cadenas

Cadenas y grupos de constantes de cadenas

¿Cuál es la idea de diseño del grupo constante de cadenas?

  1. La asignación de cadenas, al igual que la asignación de otros objetos, consume mucho tiempo y espacio. Como tipo de datos más básico, las cadenas se crean con frecuencia y en grandes cantidades, lo que afecta en gran medida el rendimiento del programa.
  2. Para mejorar el rendimiento y reducir la sobrecarga, la JVM realizó algunas optimizaciones al crear instancias de constantes de cadena y abrió un grupo de constantes de cadena para cadenas, similar a un área de caché.
    • Al crear una constante de cadena, el primer ministro consulta el grupo de constantes de cadena para ver si la cadena existe.
      • Existe: devuelve la instancia de referencia.
      • No existe: crea una instancia de la cadena y colócala en el grupo.

¿Qué es un grupo constante de cadenas?

Para evitar crear el mismo objeto de cadena y la misma asignación de memoria cada vez, Java ha realizado optimizaciones internas para almacenar literales de cadena en un área de caché, que se denomina grupo constante de cadenas .

¿Dónde está el grupo constante de cadenas?

Por favor agregue la descripción de la imagen.

Para JDK1.7 y versiones posteriores, el grupo de constantes de cadena está en el montón.

Para JDK1.6, el grupo de constantes de cadena está en el área de método.

Pregunta clásica:

String s1 = "aaa";
String s2 = "aaa";
System.out.println(s1 == s2);//true
//因为"aaa"为字面量,在编译时期就会直接在字符串常量池生成,而 s1和s2是引用的 "aaa"在字符串常量池中的引用,所以s1=s2
String s = new String("aaa");//创建了几个对象
//两个,第一个对象"aaa"会存储在字符串常量池中,因为有new 操作,所以还会在堆中创建一个对象,此时s指向的是堆中的字符串对象
String s1 = new String("aaa");
String s2 = new String("aaa");//一共创建了几个对象
System.out.println(s1 == s2);//打印true还是false
//第一个问题,一共创建了几个对象?
//3个,第一个对象因为"aaa"是字面量在编译时期就在字符串常量池中创建出来,在执行new String("aaa")时,首先回去字符串常量池equals比较是否存在"aaa"字符串,此时存在,则不再在字符串常量池中创建对象,但是有new 操作,所以又会在heap堆中创建一个对象。因为new了两次,所以在heap中创建了两个对象,加上字符串常量池中的对象一个是3个对象
//第二个问题,s1==s2是true还是false
//false,因为s1和s2分别指向的是heap中各自对象的地址值,一定是不相等的,所以为false
String s1 = "he";
String s2 = s1+new String("llo");//创建了几个对象
//4个
//在编译时期,字面量"he"和"llo"会先进字符串常量池,进行了一次new String("llo") 操作,此时会在heap中创建一个对象,运行到 "he"+new String("llo")时,还会进行拼接操作,此时还会在heap堆中再创建一个对象,所以一个会创建4对象
//下面代码创建了几个对象?
String s1 = new String("he") + new String("llo");
String s2 = s1.intern();  

	//对于jdk1.7来说,创建了5个对象,“he” "llo"字面量会先去常量池中查看是否存在,不存在,则会在常量池中创建这两个对象,然后他们都进行了new String()操作,所以还会在堆中非常量池区域再各自创建一个对象,最后 把new 出来的对象拼接起来,此时还会在堆中非常量区创建一个对象,所以一共是5个对象。
	//对于jdk1.6来说,s1和jdk1.7一样,会创建5个对象
	//s1.intern();对于jdk1.7来说,会先去字符串常量池进行eq,如果不存在相同的字符串,则会直接指向堆中s1的实例,也就是说s1.intern()返回的是s1堆中对象的指针,此时s2和s1指向的都是同一个对象,所以s1==s2 为true
	//对于jdk1.6来说,intern()操作会先去常量池进行eq,发现不存在,会在常量池创建一个“hello”对象,然后把这个“hello”返回给s2,所以对于jdk1.6来说,s1==s2 为 false
//这行代码会创建对象吗
String s1 = "java";
//不一定,因为"java"字符串大概率会在jdk源码中被先创建出来,此时s1直接会指向字符串常量池中的"java"的地址值

Respecto al uso del signo "+" para empalmar cadenas

String s1 = "he"+"llo";
//在编译时期,对于确定的常量类型,编译器进行优化,直接编译成String s1 = "hello",所以在运行时不会再发生拼接操作,直接会在字符串常量池创建一个对象
String s1 = "he";
String s2 = s1+"llo";
//对于编译器老说,在执行s2 = s1+"llo"时,编译器实际上会创建一个StringBuilder对象进行append进行拼接,然后再进行toString()方法返回,通过查看toString()方法的源码发现,实际上是进行了一次new String()操作,所以还会在deap堆中创建一个拼接后的对象,所以一共会创建3个对象

nuevo código fuente StringBuilder().toString()

Acerca del objeto String es un objeto inmutable

El hecho de que los objetos String son objetos inmutables se puede ver a través del método de empalme de String, porque todos los objetos String se empalman internamente utilizando objetos StringBuilder, y el código fuente interno del objeto StringBuilder finalmente realiza una nueva operación String ().

Aplicación de tecnología constante similar a una cadena en Java

Integer s1 = -128;
Integer s2 = -128;
System.out.println(s1 == s2);//true
Integer s3 = -129;
Integer s4 = -129;
System.out.println(s3 == s4);//false

Todos sabemos que se utilizan constantes entre los enteros -128 y 127 y que la comparación de igualdad se puede realizar directamente, pero ¿por qué?
De hecho, durante la ejecución, Integer s1 = -128; se compilará en Integer s1 = Integer.valueOf(-128). Al observar el código fuente, se descubre que Integer primero inicializará un grupo de objetos durante la inicialización interna. El alcance de este grupo de objetos es de -128 a 127. Al realizar la operación valueOf(), primero irá al grupo de objetos para encontrarlo. Si lo encuentra, lo devolverá directamente. Si no lo encuentra, lo devolverá. nuevo. Por lo tanto, si el valor entre -128 y 127 es directamente == Comparación, si se comparan con el mismo objeto, devolverá verdadero, y si se comparan fuera del rango, porque se comparan con diferentes objetos, devolverá ser falso.

El entero se inicializa a través de una clase interna estática

Por favor agregue la descripción de la imagen.

Código fuente de valueOf
Por favor agregue la descripción de la imagen.
Nota: Byte, Short, Integer, Long y Character utilizan tecnología de grupo de objetos similar.

Supongo que te gusta

Origin blog.csdn.net/XX777666/article/details/120560147
Recomendado
Clasificación