从java.lang.String#intern说起JDK6之前和JDK7及之后关于字符串常量池的区别

字符串常量池

首先,记录一点:

字符串池的确切位置没有被指定,并且可以从一个JVM实现到另一个不同。
值得注意的是,在Java 7之前,该池位于热点JVM上的堆的permgen空间中,但自Java 7以来它已被移至堆的主要部分。而在Java 8 Hotspot中,Permanent Generation已被彻底删除。

区域:HotSpot 概要:在JDK 7中,interned字符串不再分配在Java堆的永久生成中,而是分配在Java堆的主要部分(称为年轻人和老年人)以及其他人由应用程序创建的对象。此更改将导致更多数据驻留在主Java堆中,永久生成中的数据更少,因此可能需要调整堆大小。由于这种变化,大多数应用程序在堆使用中只会看到相对较小的差异,但是加载很多类或大量使用String.intern()方法的较大应用程序将会看到更显着的差异。RFE:6962931

java.lang.String#intern

然后。这个方法在jdk1.6与idk1.7之后发生了变化。主要是因为jdk1.7之后,方法区中字符串常量池的位置从方法区变成了堆上,intern()方法也做了相应的修改。
(注:jdk1.8已经移除了方法区,取而代之的是元空间)
我们看下API:


java.lang.String#intern.png

翻译一下,String类的intern()方法:一个初始为空的字符串池,它由类String独自维护。当调用 intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。 对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.intern() == t.intern()才为true。所有字面值字符串和字符串赋值常量表达式都使用 intern方法进行操作。

例子

String s = new String("1");  
s.intern();  
String s2 = "1";  
System.out.println(s == s2);  
          
String s3 = new String("1") + new String("1"); 
s3.intern();  
String s4 = "11";  
System.out.println(s3 == s4);   

如果是JDK6- ,那么运行的结果是false,false。
如果是JDK7+,运行的结果是false,true。

分析

JDK6

先针对jdk1.6来分析。intern()方法在jdk1.6中的工作原理是:

String s = new String("aaa");s.intern();在常量池中寻找常量“aaa”,如果存在,则返回这个池中的字符串,如果不存在,将s指向的堆上的对象“aaa”复制后存在常量池中,并返回池中“aaa”的一个引用(这其实说明了运行时常量池具有动态性)。

按照上面的描述开始进行分析。
String s = new String("1");
这句话实际创建了两个对象,一个是常量池中的字符串常量“1’”,另一个是堆上的String对象,s是它的引用。

s.intern();

这一句在池中寻找“1”,可以找到。所以池中没有发生改变。

String s2 = "1";

在池中寻找“1”,可以找到,所以s2指向池中“1”

所以运行之后s指向堆中对象,s2指向池中对象,当然不是指向同一个对象,结果为false.

继续往下看

String s3 = new String("1") + newString("1");

这句话执行之后,s3指向堆上值为“11”的一个对象,池中有“1”,但是没有“11”.

s3.intern();

在池中寻找“11”,没有找到,所以在池中添加了“11”

String s4 = "11";

在池中寻找“11”,能够找到,所以s4指向了池中的“11”

所以运行后,s3指向堆中的对象,s4指向池中对象,结果为false.

JDK7

再来针对jdk1.7进行分析。
字符串常量池的位置从方法区变成了堆上。jdk1.7中intern()工作原理:

String s = new String("aaa");
s.intern();

在常量池中寻找“aaa”,如果已经存在,则返回池中“aaa”这个对象。如果不存在,那么不会在常量池中复制一份s指向的对象“aaa”,而是在常量池中记录了首次出现的对象引用。假设这个引用叫p,p与s指向了堆上同一个对象,即p = s。

根据上面的描述,开始进行逐句分析。

String s = new String("1");

这句话实际创建了两个对象,一个是常量池中的字符串常量“1’”,另一个是堆上的String对象,s是它的引用。

s.intern();

这一句在池中寻找“1”,可以找到。所以池中没有发生改变。

String s2 = "1";

在池中寻找“1”,可以找到,所以s2指向池中“1”

所以运行之后s指向堆中对象,s2指向池中对象,当然不是指向同一个对象,结果为false.
这一部分与jdk1.6版本运行的结果是一样的,因为intern()查找的字符串在常量池中都已经存在了。

继续往下看

String s3 = new String("1") + newString("1");

这句话执行之后,s3指向堆上值为“11”的一个对象,池中有“1”,但是没有“11”.

s3.intern();

在常量池中寻找“11”,没有找到,此时不是在常量池中添加“11”,而是在常量池中添加一个堆上“11”对象的引用,假设这个引用叫p,p = s3.intern()。p和s3指向的是堆中的同一个对象,p = s3。

String s4 = "11".

在常量池中寻找“11”这个对象,发现p指向的对象正是“11”,那么s4也指向了堆上的“11”对象。

那么s3与s4最后都指向了堆上的“11”对象,所以s3 = s4.

思考

String s = new String("1");  
s.intern();  
String s2 = "1";  
System.out.println(s == s2);  
        
String s4 = "11";  
String s3 = new String("1") + new String("1"); 
s3.intern();  
System.out.println(s3 == s4);   

这个的结果是什么,为什么?

参考:String.intern()方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 从网上复制的,看别人的比较全面,自己搬过来,方便以后查找。原链接:https://www.cnblogs.com/...
    lxtyp阅读 1,341评论 0 9
  • String是Java基础的重要考点。可问的点多,而且很多点可以横向切到其他考点,或纵向深入JVM。 本文略过了S...
    猴子007阅读 1,376评论 0 8
  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 826评论 1 6
  • String 的声明 由 JDK 中关于String的声明可以知道: 不同字符串可能共享同一个底层char数组,例...
    CodeKing2017阅读 1,616评论 1 2
  • 参考文章:http://www.jianshu.com/p/bd972088a494 数据结构 构造函数 put ...
    Java旅行者阅读 133评论 0 0