不太熟悉字符串的可以看看这两篇文章
补坑: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
}
观察上面的代码,和debug结果。为什么s1=s2,而四个字符串的value和hash值相同的情况下s1!=s3, s3!=s4呢?
这就需要提到一个概念:字符串常量池
为了使程序的运行速度更快、 更节省内存,Java为8种基本数据类型和String类都提供了常量池
那什么是“池”呢?
“池”是编程中一种重要的提升效率的方式
比如家里向我们打生活费,有两种方法
方法1:每月定时打生活费,有可能会晚,有时候还需要我们向家里人开口要,效率很低
方法2:存到银行卡,把一年的生活费打到卡里,自己随时都可以取用
这里的方法2其实就是“池”的一种体现
为了节省存储空间以及程序的运行效率, Java 中引入了:1. Class 文件常量池 :每个 .Java 源文件编译后生成 .Class 文件中会保存当前类中的字面常量以及符号信息2. 运行时常量池 :在 .Class 文件被加载时, .Class 文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都有一份3. 字符串常量池
这篇文章我们主要讲字符串常量池
字符串常量池
JVM中的StringTable类,就是一个固定大小的HashTable
那什么样的会放入常量池中呢?
1.只要是双引号引起的,都会放在常量池中
我们重新分析文章开头的代码
StringTable这张表里面存放了很多的字符串对象,每个字符串对象都有hash和value,我们随便找一个地址(0x111)的字符串对象来举例
s1本身作为一个字符串对象,也有value和hash(注意value是一个数组),而s1 = “hello"
其实相当于s1的value指向hello这个对象
此时再让刚刚StringTable里0x111的字符串对象的hash指向s1的value,这样hello就可以借助s1存进常量池里了
此时又有一个s2 = "hello",遇到双引号,先去常量池查找是否有当前这个字符串,一查还真有,那就不会再把这个对象再存一遍了,那s2就可以获得常量池中hello的字符串对象的地址0x77了
🆗我们接着来看s3
因为s3的操作是new String 创建一个新对象,把这个新对象的value指向hello,所以后面会产生s1!=s3的情况
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对象创好
new String()里面传入一个ch,我们看看源码
源码告诉我们传入东西后将这份东西再拷贝一份,s1的value引用指向拷贝出来的ch
s2的代码就是给常量池存入abc
整个流程
我们解锁s1.intern();这行代码
这行代码意思是让s1所指的对象入池,如果常量池当中存在,就不入池