冰灯

云水禅心

  • 首页
  • 归档

  • 搜索
mybatis Dubbo Git Https ELK Elasticsearch logstash Springboot Nginx Java MQ

String常量池

发表于 2017-11-21 | 分类于 Java | 0 | 阅读次数 164

注:
这里是基于JDK8版本探究的。
JDK7及之后有所变化: 将String常量池 从 Perm 区移动到了 Java Heap区,String的intern 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象

1、 String常量池问题

String str2 = "abc";
String str3 = "abc" + "123";
String str4 = str2 + "123";
final String str5 = "ab";
String str6 = str5 + "c123";
System.out.println("str1 == str3 is "+(str1 == str3))
System.out.println("str1 == str4 is "+(str1 == str4));
System.out.println(\"str1 == str6 is \"+(str1 == str6))
System.out.println("str4 == str6 is "+(str4 == str6));

str4:
因为str2没有被final修饰,存在字符串引用str2,在编译时期未确定的,在运行时,才动态将str2+"123"连接后的新地址赋给str4,先是放到堆内存,字符串常量池是没有的,str4是对它的引用。

str3:
因为"abc","123"都是常量,在常量池里面,编译时"abc" + "123"连接后值在常量池中,并且"abc123"已在常量池中存在,最后将连接后地址赋给str3

str6:
因为str5是被final修饰了,因此是直接在常量池生成,str5+"c123"值在常量池中。
因此str1与str3、str1与str6返回true,而str1和str4返回false

总结:

1)当字符串使用"+"时,首先回去字符串常量池中查找是否已存在,存在就直接引用

2)只有当都是字符串常量使用"+"连接后,才会直接在常量池中生成。

3)存在引用连接时,就只会先在堆内存中。

2 、String的intern()方法

String str8 = "xyz567";
String str9 = "xyz";
String str10 = "567";
String str11 = new String("xyz567");
String str12 = str11.intern();
System.out.println("str8 == str11 is "+(str8 == str11));
System.out.println("str8 == str12 is "+(str8 == str12));

当前调用intern()时,str11会到常量池中查询,查询完后就返回它的引用,将引用赋给str12

String str13 = new String("a")+new String("a");
str13.intern();
String str14 = "aa";
System.out.println("str13 == str14 is "+(str13 == str14));

首先在head中创建两个对象(常量池a,堆内存str13的引用对象),而对象在"+"之后的"aa"的地址引用返回给str13,但是这时常量池中是没有"aa"的,调用intern()后,就会往常量池中放"aa"。

由于JDK7后,常量池并没有在perm pace了,而是直接在head中分一块为String pool,把堆中对"aa"的引用放一份到常量池。

str13.intern(),返回对"aa"的引用,而这时再直接定义str14对常量"aa"的引用,其指向的也是str13的引用地址,因此str13 == str14返回true。


String str13 = new String("a")+new String("a");
String str14 = "aa";
str13.intern();
System.out.println("str13 == str14 is "+(str13 == str14));

首先在head中创建两个对象(常量池a,堆内存str13的引用对象),而对象在"+"之后的"aa"的地址引用返回给str13,这时常量池中是没有"aa"的。

此时再直接定义str14,对常量"aa"引用时,直接在常量池中创建的新对象。

再调用str13.intern()时,发现常量池中已经存在"aa",就不会再将引用存一份到常量池中。

因此str13的引用与str14的引用地址是不同的,
str13 == str14返回false。

Connected to the target VM, address: 127.0.0.1:64387, transport: socket
str1 == str3 is true
str1 == str4 is false
str1 == str6 is true
str4 == str6 is false
str8 == str11 is false
str8 == str12 is true
str13 == str14 is true
str13 == str14 is false
Disconnected from the target VM, address: 127.0.0.1:64387, transport: socket
# mybatis # Dubbo # Git # Https # ELK # Elasticsearch # logstash # Springboot # Nginx # Java # MQ
mapstruct PO VO DTO等转换工具类
centos7 装 nginx 1.10.3
冰灯

冰灯

雁过无痕,敲出人生

23 日志
9 分类
11 标签
RSS
Github StackOverflow
Creative Commons
Links
  • 点滴记录
  • Zero
© 2021 冰灯