[JAVA SE] Análisis en profundidad de "String" y el código fuente subyacente correspondiente

Consejos amables

Hola a todos, soy Cbiltps. En mi blog, si hay oraciones que son difíciles de entender o puntos clave que son difíciles de expresar con palabras , tendré imágenes . ¡ Así que mi blog con fotos es muy importante ! ! !

Y hay mucho conocimiento en los comentarios del código, ¡así que los comentarios del código también son muy importantes! ! !

Este artículo primero le dice algunas reglas simples de String ,

¡ Luego escribiré otro artículo sobre la inmutabilidad de String como complemento a este artículo !

Por lo tanto, puede tratar este artículo y el siguiente artículo como una gran clase: ¡ Clase de cadena !

Introducción

De hecho, el contenido de esta sección apenas se enseña en colegios y universidades, y pocas personas lo estudian en profundidad.

Pero para mejorar y entender cómo se realiza la capa inferior de String , hay un artículo de hoy.

El contenido de este capítulo es que puedes considerarlo completamente como el cultivo de la fuerza interna, ¡y no hay daño en todos los beneficios!

El mapa de memoria dibujado hoy es más alucinante, ¡échale un vistazo más de cerca! ! !

Aspectos destacados de este capítulo y el siguiente

  • Conoce la clase String
  • Conozca el grupo de constantes de cadena
  • Comprender el uso básico de la clase String
  • Familiarizado con las operaciones comunes de la clase String
  • Conoce StringBuffer y StringBuilder

inicio de texto


1. Análisis en profundidad de cadenas


1.1 Comprender las cadenas

没有El tipo de cadena en lenguaje C , in C++y Javain, se llama String!

Simplemente entienda dos preguntas:

Qué es字符串 : use comillas dobles , " "puede tener varios caracteres, es una constante de cadena

Qué es字符 : solo puede haber un carácter entre comillas simples, que es una constante de carácter' '

注意字符串以\0结尾: ¡ No hay argumento en Java !

Inmediatamente después, abra el código fuente de String directamente , ingrese y mire el código que contiene, y descubra que se modificó por última vez , lo que indica que no se puede heredar .
inserte la descripción de la imagen aquí

1.2 Creación de cadenas

//方式1:
String str = "祥子";//字符串常量
//方式2:
String str2 = new String("花花");//调用构造方法定义
//方式3:把数组变成字符串
char[] chars = {
    
    'a', 'b', 'c'};
String str3 = new String(chars);
System.out.println(str3);

Todavía hay muchos métodos de construcción de cadenas en el documento oficial , puede echar un vistazo, ¡el blogger solo dio la mayoría de los ejemplos!

1.3 Diseño de memoria del código String

Primero escribe un código de ejemplo:

public class Main {
    
    

     public static void main(String[] args) {
    
    
        String str = "abcdef";
        String str2 = str;
        System.out.println(str);
        System.out.println(str2);
        /*打印出来是一样的!画一下内存图!*/
        
        /*其实这里的str和str2两个引用都是指向"abcdef"的,然后想一个问题,可以用str2修改"abcdef"吗?
        答案是不可以的,因为:它是字面值常量不能修改的!*/
        
        System.out.println("==============");
        str = "hello";//但是这里的修改是修改的指向!
        System.out.println(str);
        System.out.println(str2);
        /*打印出来不一样!画一下内存图!*/
    }
}

inserte la descripción de la imagen aquí

La ilustración anterior es la misma razón para imprimir, y luego mire el mapa de memoria después del cambio (punto modificado):

inserte la descripción de la imagen aquí

Luego, reescriba un fragmento de código:

public class Main {
    
    

    public static void func(String s,char[] array) {
    
    
        s = "xiangzi";
        array[0] = 'p';
    }
    
    public static void main(String[] args) {
    
    
        String str = "abcdef";
        char[] chars = {
    
    'b','i','t'};
        func(str,chars);
        System.out.println(str);
        System.out.println(Arrays.toString(chars));
    }
    /*上面的问题,一定要画草图了解一下!里面牵扯较复杂的指向问题!*/
    /*所以说,不是 传引用 就是可以改变实的值!你要看这个引用到底干啥了!!*/
}

Consulte la siguiente figura para ver el mapa de memoria y señalar los cambios del código anterior:

inserte la descripción de la imagen aquí

Entonces, ¡o bien 传引用es posible cambiar el valor real! ¡Tienes que ver lo que está haciendo esta referencia! !


2. Igualdad de comparación de cadenas


2.1 Comparación de contenido

La comparación de contenido utiliza el método de igualdad para la comparación. ¡Simplemente puede ir al código fuente o al documento para averiguar cómo usarlo !

Hablemos de los puntos a los que prestar atención en el método de igualdad :

 public static void main(String[] args) {
    
    
        String str1 = null;
        /*使用equals的时候要注意:一定要预防空指针异常!*/
        String str2 = "11";//如果想要修改的话,就必须通过反射修改
//        System.out.println(str1.equals(str2));//这样子就是空指针异常
        System.out.println(str2.equals(str1));//这里的str2不是空指针,就不会报错的
    }

2.2 Comparación de direcciones

Vaya directamente al código (incluidos los puntos de conocimiento y el contenido ampliado):

public class Main {
    
    
    public static void main4(String[] args) {
    
    
        String str1 = "hello";
        String str2 = new String("hello");
        System.out.println(str1 == str2);
        /*其实这里比较的不是内容,而是地址! 地址不一样,运行的结果就是false!*/

   /**然后下面做一点铺垫(涉及到JVM的知识):
    *
    * Class文件常量池:Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量
    * 池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加
    * 载后存放到方法区的运行时常量池中。
    *
    * 运行时常量池:当程序把编译好的字节码文件加载到JVM当中后,会生成一个运行时常量池(在方法区,就是从磁盘到内存),
    * Class文件常量池会变成运行时常量池。
    *
    * 字符串常量池:本质是一个哈希表(StringTable),JDK1.8开始放在了堆里面,里面存的是驻留字符串的引用,
    * 在堆中的字符串实例被这个哈希表引用之后就等同被赋予了”驻留字符串”的身份,
    * 在JVM中字符串常量池被所有类共享。
    *
    * 什么是哈希表:其实就是一个数据结构,描述和组织数据的一种方式,非常的块!
    *  如果你想知道StringTable如何实现的,可以直接去看JVM的源代码,但是使用C++写的!
    */

Eche un vistazo al mapa de memoria del código anterior:

inserte la descripción de la imagen aquí

Luego mira el siguiente fragmento de código:

public static void main(String[] args) {
    
    
        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1 == str2);
        /*这里肯定就是true了!*/
    }

Su mapa de memoria se ve así:

inserte la descripción de la imagen aquí

Cuando dibujo la imagen aquí, la dirección en el lado derecho de str2 es 0x334, preste atención cuando la lea, ¡será problemático cambiarla!

Con respecto a los puntos de conocimiento anteriores, si desea verificar, puede abrir el código de desensamblaje para ver:

inserte la descripción de la imagen aquí
En este punto, ya sabes cómo se crea la cadena, ¡apreciemos cómo se implementa el código fuente!

En el código fuente de la JVM se puede ver:

cómo se coloca un elemento;

Cómo se crea StringTable;

Cómo se convierten los datos en hash, etc.

¡Todo esto está escrito en C++, y algunos blogueros no pueden entenderlo!

¡Vea que JAVA está de pie sobre los hombros de gigantes!

inserte la descripción de la imagen aquí

Para fortalecer la comprensión, continúe mirando hacia abajo:

public class Main {
    
    
    public static void main(String[] args) {
    
    
        String str1 = "hello";
        String str2 = "he" + "llo";//此时 他两都是常量,编译的时候,就已经确定好了是"hello"
        String str3 = "he";
        String str4 = str3 + "llo";//此时str3是一个变量 -> 编译的时候,不知道是啥? str4不是一个完整的对象!
        /*拼接的hello并不是在常量池里面,拼接的是一个单独的对象!所以运行结果就是false!*/
        System.out.println(str1 == str4);
    }
}

En el código anterior, str2 es " hola ", vea el código de desmontaje a continuación:

inserte la descripción de la imagen aquí

Echa un vistazo a la gráfica de memoria:

inserte la descripción de la imagen aquí

El siguiente ejemplo es más problemático (importante):

public static void main(String[] args) {
    
    
        String str1 = "11";
        String str2 = new String("1") + new String("1");//这里创建的对象是StringBuilder对象!
        System.out.println(str1 == str2);
    }

Ir directamente al mapa de memoria:

inserte la descripción de la imagen aquí

Además, es lo mismo mirar el código de desmontaje para verificar la imagen de arriba:

inserte la descripción de la imagen aquí

Entonces si este es el caso:

//代码1
public static void main(String[] args) {
    
    
        String str2 = new String("1")+new String("1");
        String str1 = "11";
        System.out.println(str1 == str2);//如果反过来依旧是false
    }

Mira abajo:

//代码2
public static void main(String[] args) {
    
    
        String str2 = new String("1")+new String("1");
        str2.intern();//手动入池
        String str1 = "11";
        System.out.println(str1 == str2);//这里就是true了
    }

Cuando llegue aquí, no dibujaré más, soy casi un inútil y no quiero dibujar más...

De hecho, el principio se explica simplemente:

El código 1 es el mismo código que la demostración anterior,

El código 2 pondrá el " 11 " deletreado en el grupo manualmente,

Luego, cuando cree una cadena, ¡verificará si hay un punto directo a esta cadena!

El problema de la comparación de cadenas está terminado aquí, ¡todos, miren bien y aprendan!

fin del texto

De hecho, es posible escribir aquí, pero quiero escribir de manera más completa .

¡Pero demasiado tiempo no es una buena solución!

¡Escribiré un artículo más tarde, todavía sobre String !

¡Se trata de que String sea inmutable y lo haga cambiable !

¡Espéralo con ansias! ¡Gracias de nuevo por sus gustos y atención!

Supongo que te gusta

Origin blog.csdn.net/Cbiltps/article/details/122535985
Recomendado
Clasificación