概述
这几天在学习jvm内存结构的时候,发现很多文章关于运行时常量池这个概念没有说清,这里自己总结了一下,有不当之处欢迎指正;以下是参考文章:
- JDK1.8关于运行时常量池, 字符串常量池的要点
- Java内存管理
尤其是看了第一篇之后,没想到一个简简单单的String还有这么东西,所以自己也是简单测了一下,加深对jvm的理解。
测试之前先简单说明一下概念:
- 首先是方法区和永久代,目前有三大Java虚拟机:HotSpot,oracle JRockit,IBM J9。目前使用最多的就是HotSqot,而另外两个是不存在永久代这种说法的,所以可以认为方法区和永久代的关系就类似于类和对象的概念,永久代即是对方法区的实现,在jdk1.8之后,方法区的实现由永久代变为元空间;
- 然后是字符串常量池,字符串常量池属于运行时常量池的一部分,而运行时常量池是属于方法区的,但是在jdk1.7中字符串常量池被单独从方法区中拿到了堆中, 运行时常量池其他部分任然在方法区中;1.8中方法区被元空间取而代之,拿到了本地内存中,此时,字符串常量池任然在堆中。
- intern()方法:在<深入理解Java虚拟机>一书中关于该方法的解释是:
String.intern()是一个Native方法,它的作用是:如果字符常量池中已经包含一个等于此String对象的字符串,则返回常量池中字符串的引用,否则,将新的字符串放入常量池,并返回新字符串的引用。
以下是相关测试
- String 和new String的区别
String s1 = "123";
String s2 = new String("123");
System.out.println(s1 == s2); //false
这里很好理解,a是存储在字符串常量池中,而b是new出来的,存放在堆中;注意,虽然上面说了字符串常量池被单独拿到了堆中,但是他和堆中存放的对象任然是隔离的;
- new String到底创建了几个对象
String s1 = new String("ab");
String s2 = "ab";
System.out.println(s1 == s2 ); // false
System.out.println(s1.intern() == s2 ); // true
通过该例可以看出new String创建了两个对象,先是在字符串常量池中创建了"ab"常量即s1.intern(),然后在堆中开辟了一块内存存储ab变量即s1;这里有个误区,我在看第一篇参考文章底下的评论的时候,有人认为既然new String创建了两个对象,那么第4行的结果应该是true;这句话前半段没错,new String虽然创建了两个对象,但是实际上只会指向堆中的那个对象,而常量池中的对象是通过intern()指向的;
- String + String创建了几个对象
String s1 = "a"+"b";
String s2 = "ab";
System.out.println(s2 == s1); // true
这里创建了1个对象,jvm编译阶段过编译器优化后会把字符串常量直接合并成"ab",所有创建对象时最多会在常量池中创建1个对象。
- new String+new String
String s1 = "aabb";
String s2 = new String("aa")+new String("bb");
System.out.println(s1 == s2); //false
System.out.println(s1 == s2.intern()); //true
此时第二行创建过程中不会在字符串常量池中生成aabb字符串,看以下论证:
String s1 = "a";
String s2 = "b";
String s3 = s1 + s2;
String s4 = new String("ab");
System.out.println(s4.intern() == s3);
// false
System.out.println(s3 == s4); // false
如果在"a"+"b"
拼接的过程中,在字符串常量中产生了"ab",那么第一行的输出应该为true而不是false,所以可以的到new String(“a”)+new String(“b”)的创建过程并不会在常量池中生成"ab";
但是,该论证是有缺陷的,s1和s2虽然是常量,但是在s3中是变量,相当于new出来的,所以第二行输出为false,因为两个都可以看做是new出来的,这样一来也能解释第一行的输出,因为一个在堆中,一个在字符串常量池中,自然为false;
关于这部分论证可以看下这两篇文章JAVA中String.intern的理解、new String(“123”) 创建了几个对象?
最后
以上就是笨笨小蜜蜂为你收集整理的String和new String的全部内容,希望文章能够帮你解决String和new String所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复