java字符串、常量池和intern方法理解

1 对于常量字符串,在编译的时候就会将这个字符存入常量池

   常量池中其实有一个table表对象维护所有的字符串

 

2 对于 new String("abc")的理解:

   有种说法new String会在堆中和常量池中创建两个对象,这种说法其实没错

   因为括号里面出现的"abc"其实相当于String s1 = "abc"的作用,这个对象就已经存入了常量池

   但是如果出现new String("a") + new String("b") + new String("c") 这种,那么常量池只有a b c 三个对象,

   但是并没有abc这个对象。对于 new String(str1); 这个时候str1的所代表的对象是不会存入常量池的,而是存入堆中

 

3 对于 String test = “a” + “b” + “c”:

   这个时候常量池里面其实只有一个对象,因为 a b c 它们在编译的时候就会生成一个abc字符串,

   所以只有一个对象被创建反编译过后成了 String test = “abc”:

   同理:String s = new String("abc" + "def");反编译成为了 String s = new String("abcdef");也就是创建了两个对象

   但是:String s = new String("abc" + str); 就不一样了

4 对于变量字符串参与+运算

   String s = “abc” + str;

   因为编译期间无法确认str,所以不能以常量来计算,这个时候就得使用new来操作

   但是如果 str 是 final 类型,那么又不一样了,他就是一个常量了,以后代码中出现的str都会被

   它的字符串来代替

5 常量池保存的是字符串还是字符串的引用?

   其实回答这个问题需要区分jdk版本

   jdk<=6 : 那么常量池中肯定保存的都是字符串

   jdk>=7 : 那么常量池中保存可以是字符串,也可以是引用

         那什么时候会出现保存引用呢?

         这就需要了解jdk7以后,常量池被移到堆中,并且intern方法机制有改变,这个方法

         在jdk7以前,机制是看常量池中有没有指定的字符串,如果没有则复制一份字符串到

         常量池中;jdk7以后,区别是如果常量池没有则会把堆中的字符串的引用复制一份到

         常量池中。

   所以字符串可以保存在常量池中,也可以保存在堆中;

   jdk7以后,常量池中可以保存字符串,也可以保存字符串的引用。

 

 

其实从图2 就可以得出一些结论:

   a 字符串其实可以存储在两个地方,池和堆中都有存储,否则也不会出现intern这个方法去

   常量池中找有没有这个字符串,那说明有的字符串根本就不在池中

      比如 new String(String.valueOf(123))

      new String("a") + new String("b")

      创建的对象都是在堆中

6 对于String.intern方法(这个方法只有new对象才能调用)

   jdk<7:则是将字符串本身在常量池中查找,如果有,则返回常量池中的引用,

      没有则在常量池中新建字符串本身,然后返回常量池的引用

   jdk>=7:则是将字符串本身在常量池中查找,如果有,则返回常量池中的引用,这里没有变化,

      如果没有则会将堆中的引用传递给常量池,然后返回这个指向堆的引用

 

7 对于不同的版本的jdk常量池的位置(方法区也被叫做永久带)

   jdk6:常量池放在方法区(永久带)中

   jdk7:常量池放在堆中,方法区中的其余的还在方法区(永久带)

   jdk8+:常量池放在堆中,方法区(永久带)被取消,被放在元空间

   可以使用jdk8测试:

   jvm参数:-Xmx20m -Xms20m -XX:-UseGCOverheadLimit

   这里的-XX:-UseGCOverheadLimit是关闭GC占用时间过长时会报的异常

   运行下面代码:

      public static void main(String[] args) throws Throwable {

      List<String> list = new ArrayList<String>();

      int i=0;

      while(true){

         list.add(String.valueOf(i++).intern());

      }

}

异常信息是:java.lang.OutOfMemoryError: Java heap space

 

不得不承认,我基本不转载,因为想自己消化,然后总结,记录笔记

但是一定要学会拿来主义:参考 https://blog.csdn.net/baidu_31657889/article/details/52315902

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值