补坑:Java的字符串String类(3):再谈String

不太熟悉字符串的可以看看这两篇文章

补坑:Java的字符串String类(1)-CSDN博客

补坑:Java的字符串String类(2):一些OJ题目-CSDN博客

字符串创建对象

    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        String s3 = new String("hello");
        String s4 = new String("hello");
        System.out.println(s1 == s2); // true
        System.out.println(s1 == s3); // false
        System.out.println(s3 == s4); // false
    }

补坑:Java的字符串String类(3):再谈String_第1张图片 

观察上面的代码,和debug结果。为什么s1=s2,而四个字符串的value和hash值相同的情况下s1!=s3, s3!=s4呢?

这就需要提到一个概念:字符串常量池

为了使程序的运行速度更快、 更节省内存Java8种基本数据类型和String类都提供了常量池

那什么是“池”呢?

“池”是编程中一种重要的提升效率的方式

比如家里向我们打生活费,有两种方法

方法1:每月定时打生活费,有可能会晚,有时候还需要我们向家里人开口要,效率很低

方法2:存到银行卡,把一年的生活费打到卡里,自己随时都可以取用

这里的方法2其实就是“池”的一种体现

为了节省存储空间以及程序的运行效率, Java 中引入了:
1. Class 文件常量池 :每个 .Java 源文件编译后生成 .Class 文件中会保存当前类中的字面常量以及符号信息
2. 运行时常量池 :在 .Class 文件被加载时, .Class 文件中的常量池被加载到内存中称为运行时常量池,运行时常
量池每个类都有一份
3. 字符串常量池

这篇文章我们主要讲字符串常量池


字符串常量池

JVM中的StringTable类,就是一个固定大小的HashTable

补坑:Java的字符串String类(3):再谈String_第2张图片

那什么样的会放入常量池中呢?

1.只要是双引号引起的,都会放在常量池中

我们重新分析文章开头的代码

StringTable这张表里面存放了很多的字符串对象,每个字符串对象都有hash和value,我们随便找一个地址(0x111)的字符串对象来举例

补坑:Java的字符串String类(3):再谈String_第3张图片补坑:Java的字符串String类(3):再谈String_第4张图片

s1本身作为一个字符串对象,也有value和hash(注意value是一个数组),而s1 = “hello"

其实相当于s1的value指向hello这个对象

补坑:Java的字符串String类(3):再谈String_第5张图片

此时再让刚刚StringTable里0x111的字符串对象的hash指向s1的value,这样hello就可以借助s1存进常量池里了

补坑:Java的字符串String类(3):再谈String_第6张图片

此时又有一个s2 = "hello",遇到双引号,先去常量池查找是否有当前这个字符串,一查还真有,那就不会再把这个对象再存一遍了,那s2就可以获得常量池中hello的字符串对象的地址0x77了

补坑:Java的字符串String类(3):再谈String_第7张图片

我们接着来看s3

因为s3的操作是new String 创建一个新对象,把这个新对象的value指向hello,所以后面会产生s1!=s3的情况

补坑:Java的字符串String类(3):再谈String_第8张图片

2.intern方法

    public static void main(String[] args) {
        char[] ch = new char[]{'a', 'b', 'c'};
        String s1 = new String(ch); 
        //s1.intern();
        String s2 = "abc"; 
        System.out.println(s1 == s2);
    }

先把ch和s1对象创好

补坑:Java的字符串String类(3):再谈String_第9张图片

new String()里面传入一个ch,我们看看源码

源码告诉我们传入东西后将这份东西再拷贝一份,s1的value引用指向拷贝出来的ch

补坑:Java的字符串String类(3):再谈String_第10张图片

s2的代码就是给常量池存入abc

整个流程

补坑:Java的字符串String类(3):再谈String_第11张图片

我们解锁s1.intern();这行代码

这行代码意思是让s1所指的对象入池,如果常量池当中存在,就不入池

补坑:Java的字符串String类(3):再谈String_第12张图片

 

你可能感兴趣的:(JAVASE基础,java,开发语言)