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 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。

不同JDK版本之间的intern()方法的区别-JDK6 VS JDK6+的更多相关文章

  1. 〖Linux〗多个JDK版本之间快速切换

    由于工作的需要,经常要切换JDK版本比如我HOME目录下有三个JDK版本: ~/apt/jdk1..0_34 # JDK6 ~/apt/jdk1..0_67 # JDK7 ~/apt/jdk1..0_ ...

  2. Windows下多个JDK版本之间的切换

    一.JDK版本切换批处理脚本   我们平时在window上做开发的时候,可能需要同时开发两个甚至多个项目,有时不同的项目对JDK的版本要求有区别,这时候我们可能会在一台电脑上安装多个版本的JDK,如下 ...

  3. ubuntu中 不同JDK版本之间的切换

    Ubuntu中JDK 的切换前提是同时安装了多个版本,如jdk7和jdk8,若要切换,在终端输入: sudo update-alternatives --config java sudo update ...

  4. Caffe 不同版本之间layer移植方法

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/52185521 (前两天这篇博客不小心被 ...

  5. maven项目编译运行时提示jdk版本过低问题解决方法

    明明使用的是1.8jdk,但是运行项目时提示使用的是java版本是1.5,版本过低. 修改pom.xml,添加如下: <build> <plugins> <plugin& ...

  6. String类中intern方法的原理分析

    一,前言 ​ 昨天简单整理了JVM内存分配和String类常用方法,遇到了String中的intern()方法.本来想一并总结起来,但是intern方法还涉及到JDK版本的问题,内容也相对较多,所以今 ...

  7. String的Intern方法详解

    引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String.这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念.常量池就类似一个JAVA系统级别提供的缓存.8种 ...

  8. 解决java.io.IOException: Cannot run program "javac"问题,并设置jdk版本

    原因:没有配置java路径 解决方法:设置java_home路径 设置jdk版本是10的方法:在sbt文件中添加一行: javacOptions := Seq(") 然后重新执行命令:sbt ...

  9. IntelliJ IDEA 中如何配置多个jdk版本即(1.7和1.8两个jdk都可用)

    IntelliJ IDEA使用教程 (总目录篇) 有时候需要看Java源码,但是 Java 1.7 和 Java 1.8的差别的关系,有时候你想查看不同jdk版本的Java源码. 或者你的项目需要测试 ...

随机推荐

  1. 带头结点的双向循环链表----------C语言

    /***************************************************** Author:Simon_Kly Version:0.1 Date: 20170520 D ...

  2. 51nod1787最大子方阵

    51nod1787最大子方阵 我在51nod上面切的第一道题 我在51nod上面切的第一道8级题 我在51nod上面切的第一道8级题的一血 题目大意 有一个n*m的矩阵,矩阵中的每一个元素是'X'或者 ...

  3. centos7.4 系统优化

    static 表示该服务与其他服务相关联,不能单独设置该服务的启动状态 disabled 表示禁止开机启动 enabled 表示允许开机启动 auditd.service enabled autovt ...

  4. JAVA API 实现hdfs文件操作

    java api 实现hdfs 文件操作会出现错误提示: Permission denied: user=hp, access=WRITE, inode="/":hdfs:supe ...

  5. [已解决]报错SyntaxError: Non-ASCII character '\xe6'

    解决方案:开头加上 # -*- coding: utf-8 -*

  6. 编写一个简单的内核驱动模块时报错 “/lib/modules/3.13.0-32-generic/bulid: 没有那个文件或目录。 停止。”

    编写一个简单的内核驱动模块 static int hello_init() { printk(“hello,I am in kernel now\n”); ; } void addfunc(int a ...

  7. Linux 父进程发送信号杀死子进程

    #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <signal. ...

  8. Struts2开发环境搭建

    eclipse配置struts2开发环境: 1.导入jar包:复制Struts\apps\struts2-blank\WEB-INF\lib下的所有jar包到当前项目的lib文件夹下 2.在web.x ...

  9. C中空指针、NULL与0

    空指针是指确保可以没有指向任何一个对象的指针.空指针常量值通常使用宏定义NULL来表示. 空指针和任何非空指针比较都不相等,因此经常作为函数异常时的返回值使用. 链表也经常在数据末尾放一个空指针提示后 ...

  10. [JZOJ6353] 【NOIP2019模拟】给

    题目 题目大意 对于所有的整数\(k \in [1,n]\),求叶子结点有\(k\)个的二叉树个数,满足每个非叶子结点都有两个儿子,并且对于每个叶子结点,从根节点到它经过的向左的边数少于等于\(m\) ...