String 常量池

特别说明:本文只是作者经过自己理解后写的笔记,如有误导之处还请指出!

  • jdk1.6

1.6中Perm Space(常量池在其中) 和 Java Heap 是独立的

  1. 当出现"1"这种双引号字符串声明时,会校验字符串常量池,如果池中没有和当前字符串值相等的,那么在池中创建"1"这个字符串常量,如果池中已存在了,那就不用创建了,只要保证当前字符串在池中有就可以了,例如下列语句任意一句只要出现,就要保证"1"这个字符串在常量池中存在:
    String s1 = "1";
    String s2 = new String("1");
    String s3 = new String("1") + new String("2");
  2. 调用intern()方法,保证字符串在常量池中存在,该方法的返回值是指向指向池中当前常量的一个引用(注意是一个引用),例子如下:
    1. String s4 = new String("3"); s4.intern(); 这两句话中的s4引用的指向是在Java Heap中的 new String("3")对象,常量池中确实有"3"这个字符串了,但是是第一句话创建的,所以第二句话s4.intern();基本没什么用,如果想要让一个引用指向常量池中的"3"就可以这样写:String s5 = s4.intern();此时的s5就是指向常量池的一个引用,所以如果用比较语句比较s4和s5:
      • s4 == s5 ; 结果是false,因为s4指向了Java Heap 中的"3"对象,而s5指向了Perm Space中的常量池中的"3",所以地址不同,结果为false
      • 用equals比较,因为值相同,所以结果为true
    2. String s6 = new String("4") + new String("5"); s6.intern(); 这两句代码的意思理解非常重要,第一句代码一共创建了几个对象?(答案:5个,前提是常量池为空。第一个是Perm Space常量池中的"4",第二个Perm Space是常量池中的"5",第三个是Java Heap堆中的new String("4")对象,第四个是Java Heap堆中的new String("5")对象,第五个是Java Heap堆中的"45"对象),经过上面括号的解释,也就知道了s6.intern()这句话的重要了,因为在没执行这句话的时候,池中不存在"45"这个字符串常量,当执行s6.intern()时,常量池中创建了"45"这个常量,所以此时的intern()方法就非常重要了,所以下面代码的结果就比较容易理解了:
      String s6 = new String("4") + new String("5");
      String s7 = s6.intern();
      String s8 = "45";
      System.out.println(s6 == s7);	//jdk1.6 false  jdk1.7 true
      System.out.println(s6 == s8);	//jdk1.6 false  jdk1.7 true 
      System.out.println(s7 == s8);	//jdk1.6 true   jdk1.7 true
  • jdk1.7

1.7中常量池是在Java Heap里面,所以跟1.6的区别是,对于一个字符串,只要保证该字符串在常量池中有一个对象或者有一个指向等值的在Java Heap区的对象的一个引用(说白了就是常量池中不再是保证一定是对象了,可能是对象,也可能是指向Java Heap区的某个对象的一个引用)

  1. 当出现"1"这种双引号字符串声明时,如果池中没有"1"对象且也没有引用是指向Java Heap区的"1"对象的,那么就会在常量池中创建"1"对象,以下语句都会创建:
    String s1 = "1";
    String s2 = new String("1");
    String s3 = new String("1") + new String("2");
  2. 调用intern()方法,保证字符串在常量池中存在对应的对象或者指向Java Heap相同内容的引用,看例子:
    1. String s4 = new String("3"); s4.intern(); 第一句话就已经在常量池中创建了"3"对象了,所以第二句s4.intern()就没有什么作用了,如果还是想要一个引用指向常量池中的"3",只需要 String s5 = s4.intern(); 这样s5就是指向常量池中的"3"对象的一个引用,可以继续比较s4和s5,因为s4引用的指向是在Java Heap中的 new String("3")对象,所以:
      1. s4 == s5 结果是false,因为s4指向的是Java Heap中的new String("3")对象,而s5指向的是Java Heap中的常量池中的"3"对象,所以s4和s5虽然都指向的是Java Heap区,但是地址不同,结果是false
      2. 用equals比较,因为内容相同,所以结果为true
    2. String s6 = new String("4") + new String("5"); s6.intern(); 同样再来看这两句代码,第一句代码一共创建了几个对象?(答案:5个,前提是常量池为空。第一个是常量池中的"4",第二个是常量池中的"5",第三个是Java Heap堆中的new String("4")对象,第四个是Java Heap堆中的new String("5")对象,第五个是Java Heap堆中的"45"对象),而第二句代码s6.intern()的意义对于jdk1.6和jdk1.7的意义就不同了,如果常量池中不存在"45"这个字符串对象,那么jdk1.6的做法是在常量池中创建一个"45"对象,而jdk1.7的做法是储存一个指向Java Heap(常量池以外的部分)里面"45"对象的一个引用,也就是说jdk1.7没有创建对象,只是储存了一个引用,所以此时的intern()方法的理解就非常重要了,再看一遍下面的代码结果,理解一下:
      String s6 = new String("4") + new String("5");
      String s7 = s6.intern();
      String s8 = "45";
      System.out.println(s6 == s7);	//jdk1.6 false  jdk1.7 true
      System.out.println(s6 == s8);	//jdk1.6 false  jdk1.7 true 
      System.out.println(s7 == s8);	//jdk1.6 true   jdk1.7 true

总结:

  1. jdk1.6中的常量池是在Perm Space区域中,和Java Heap是独立的;而jdk1.7中的常量池是在Java Heap中的一个区域里
  2. jdk1.6的常量池以为独立于Java Heap,所以只保存对象;而jdk1.7中的常量池是在Java Heap区域,所以会储存对象或者引用(指向Java Heap区域某个对象的引用,比如在调用intern()方法的时候获取该引用)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值