zoukankan      html  css  js  c++  java
  • 《Java 底层原理》String字符串详解

    前言

    Java 字符串底层是如何存储的,如何提高性能的,今天就来好好了解一下。

    字符串的存储结构

    Jvm 有专门的字符串常量池用于存放字符串,存放字符串的数据结构是HashTable。

    HashTable的数据结构如下:

    看个案例:

    public class StringDemo {
        public static void main(String[] args) {
            String a = "11";
            String b = new String("11");
    
            System.out.println("a的HashCode:"+a.hashCode());
            System.out.println("b的HashCode:"+b.hashCode());
    
            System.out.println("a==b :"+(a==b));   // 比较的指针地址
            System.out.println("a.equals(b) :"+ a.equals(b));   // 比较的是hashCode
        }
    }

    运行结果:

    通过案例我们来详细说明一下,Jvm如何创建一个String字符串的。

    String 字符串会创建多少个Oop(Oop 是指Java 对象在Jvm中的存在形式)?

    String a = "11";       

    我们可以通过idea 来看创建了多少个Oop。

    调式字符串赋值后。 char[] 和 String 都加一了。

    说明创建了两个Oop 

    char[] 对应 TypeArrayKlass

    String  对应  TypeArrayOopDesc

    画图说明字符串在Jvm 中的存在形式:

    String a = new String ("11");   -- 创建了3和Oop

    再来看一下String 拼接的案例

    public class StringDemo2 {
        public static void main(String[] args) {
            String s1 = "1";
            String s2 = "2";
            String s3 = s1+s2;
            String s4 = "12";
            System.out.println("s3 == s4: "+(s3 == s4));
        }
    }

    运行结果:

    拼接字符串的实现原理用一句话完美解释:

    new StringBuilder(s1).append(s2).toString();    // toString 方法中有一个new String的逻辑。

    并且拼接后的字符串是不放入常量池的。 看看toString 的源码

    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

    new String(value, 0, count) ,这种方式创建的String 不放入常量池。

    那有什么方式可以将拼接的字符串放入常量池吗?答案是肯定的。

    public class StringDemo2 {
        public static void main(String[] args) {
            String s1 = "1";
            String s2 = "2";
            String s3 = s1+s2;
            s3.intern();       // 将拼接的字符串放入常量池
            String s4 = "12";
            System.out.println("s3 == s4: "+(s3 == s4));
        }
    }

    intern 方法就是将拼接的字符串放入常量池。

    再来看一个案例:

    public class StringDemo2 {
        public static void main(String[] args) {
            final String s1 = "1";
            final String s2 = "2";
            String s3 = s1+s2;
            String s4 = "12";
            System.out.println("s3 == s4: "+(s3 == s4));
        }
    }

    运行结果:

    原因是s1,s2 都是final修饰,表示不会变,那么String s3 = s1+s2; 其实也不会变,所以和 s3 = “12” 等价。   

    总结

    String 字符串对应数据存放在字符串常量池。

    拼接字符串实际就是StringBuilder 拼接。

    final 修饰的情况。

    intern 方法的作用是 将字符串加入常量池。

    This moment will nap, you will have a dream; But this moment study,you will interpret a dream.
  • 相关阅读:
    POJ1251 Jungle Roads 【最小生成树Prim】
    聪明的kk
    日积月累:weightSum和layout_weight属性合用
    ubuntu 下舒畅的使用libreoffice
    maple 教程
    龙、虎、鲸书杂谈
    百度没出新算法之前这样的最好的的优化方案
    DWR入门实例(二)
    Android应用公布的准备——生成渠道包
    leetcode第一刷_Spiral Matrix II
  • 原文地址:https://www.cnblogs.com/jssj/p/14317361.html
Copyright © 2011-2022 走看看