• 不同JDK版本之间的intern()方法的区别-JDK6 VS JDK6+


     

    String s = new Stirng(“a”);

    s.intern();

    JDK6:当调用intern()方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,将此字符串对象添加到字符串常量池中,并且返回该字符串的引用。

    JDK6+:当调用intern()方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,如果该字符串对象已经存在于Java堆中,则将堆中此对象的引用添加到字符串常量池中,并且返回该引用;如果堆中不存在,则在池中创建该字符串并返回其引用。

    注:在JDK1.6的时候,字符串常量池是存放在Perm Space中的(Perm Space和堆是相隔而开的),在1.6+的时候,移到了堆内存中

    JDK6:返回false false

    【注意:String s = new String("a")的时候, “a”会被首先创建,放入字符串常量池中,然后new出的对象放在堆中,在调用intern()的时候,会尝试将字符串对象放入字符串常量池中,但是发现字符串常量池中已经有了,就不能放了,在String s2 = "a"的时候,会先在常量池中寻找有没有对应的字符串,如果有,就直接返回它的引用,详情可见面试题笔记中的==与equal    在String s3 = new String("a") + new String("a"),字符串常量池是不会创建“aa”这个字符串的,因为“”中只有单个a,所以在调用intern()的时候,会尝试将“aa”也就是堆中的那个字符串对象放入常量池中,并返回字符串常量池中“aa”的引用,但是由于常量池中放的相当于是一个对象副本,当返回它的引用时,地址是永久区的,因此不会相等】

    JDK6+:返回false true

    J

    【注意:String s = new String("a")的时候, “a”会被首先创建,放入字符串常量池中,然后new出的对象放在堆中,在调用intern()的时候,会尝试将字符串对象放入字符串常量池中,但是发现字符串常量池中已经有了,就不能放了,在String s2 = "a"的时候,会先在常量池中寻找有没有对应的字符串,如果有,就直接返回它的引用,详情可见面试题笔记中的==与equal    在String s3 = new String("a") + new String("a"),字符串常量池是不会创建“aa”这个字符串的,因为“”中只有单个a,所以在调用intern()的时候,会尝试将“aa”也就是堆中的那个字符串对象的引用放入常量池中,并将该引用返回,由于这两个都是同一个地址引用,于是相等】

    再来看第二段代码:

    public static void main(String[] args) {
    String s = new String("1");
    String s2 = "1";
    s.intern();
    System.out.println(s == s2);

    String s3 = new String("1") + new String("1");
    String s4 = "11";
    s3.intern();
    System.out.println(s3 == s4);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    打印结果是

    jdk6 下false false
    jdk7 下false false

    第一段代码和第二段代码的改变就是 s3.intern(); 的顺序是放在String s4 = “11”;后了。这样先执行String s4 = “11”;声明 s4 的时候常量池中是不存在“11”对象的,执行完毕后,“11“对象是 s4 声明产生的新对象。然后再执行s3.intern();时,常量池中“11”对象已经存在了,不需要新建任何对象或引用; 因此 s3 和 s4 的引用是不同的。(一个指向常量池,一个指向Java堆)。

    第二段代码中的 s 和 s2 代码中,s.intern();,这一句往后放也不会有什么影响了,因为对象池中在执行第一句代码String s = new String(“1”);的时候已经生成“1”对象了。下边的s2声明都是直接从常量池中取地址引用的。 s 和 s2 的引用地址是不会相等的。

    小结

    从上述的例子代码可以看出 jdk7 版本对 intern 操作和常量池都做了一定的修改。主要包括2点:

    将String常量池从Perm区移动到了Java Heap区

    String#intern 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。

  • 相关阅读:
    学习Java的Day02
    学习Java的Day01
    多线程的了解
    几个MQ的区别
    HTML5——存储(cookie、localStorage、sessionStorage)的区别
    dubbo mock配置
    Springboot分布式,excel导出,运用POI导出,前端用的jsp
    oracle 添加字段和添加注释
    可以重复的Map:IdentityHashMap
    数组转list问题
  • 原文地址:https://www.cnblogs.com/zyy1688/p/10825507.html
Copyright © 2020-2023  润新知