String的intern()方法浅析

2 篇文章 0 订阅
订阅专栏

简介

String.intern()方法是一种手动将字符串加入常量池中的native方法,原理如下:如果在当前类的常量池中存在与调用intern()方法的字符串等值的字符串,就直接返回常量池中相应字符串的引用,否则在常量池中复制一份该字符串(Jdk7中会直接在常量池中保存当前字符串的引用),并将其引用返回;因此,只要是堆中等值的String对象,使用intern()方法返回的都是常量池中同一个String引用,所以,这些等值的String对象通过intern()后使用==是可以匹配的。

预备知识

一、创建String对象的两种方式 

创建String对象分为在堆中创建和在字符串常量池中创建。 

1、在字符串常量池中创建String对象

String str1 = "计算机";
String str2 = "计算机";
System.out.println(str1 == str2);

第一行代码

  • 执行到括号中“计算机”的时候,会在字符串常量池中添加“计算机”对象。
  • 然后将栈中的str1变量指向该对象。 

第二行代码

  • 执行到括号中“计算机”的时候,发现字符串常量池已存在“计算机”对象。
  • 为避免重复创建对象,将栈中的str2变量指向字符串常量池已存在的对象,字符串常量池存在的原因正是如此。 

 补充:

//常量字符串的"+"操作,编译阶段直接会合成为一个字符串。
String str = "计算" + "机"; //编译时合并成String str = "计算机";

//对于final字段,编译期直接进行了常量替换。
final String str1 = "计算";
final String str2 = "机";
String str3 = str1 + str2; //编译时直接替换成了String str3 = "计算" + "机";

2、在堆中创建String对象

String str1 = new String("计算机");
String str2 = new String("计算机");
System.out.println(str1 == str2);

第一行代码

  • 执行到括号中“计算机”的时候,会在字符串常量池中添加“计算机”对象。
  • 执行完毕后会在堆中创建“计算机”对象,并将栈中的str1变量指向该对象。 

第二行代码

  • 执行到括号中“计算机”的时候,发现字符串常量池已存在“计算机”对象。
  • 执行完毕后会因为new关键字在堆中创建出一个新的对象,并将栈中的变量str2指向该对象。  

 二、不同jdk版本中的intern()实现

jvm对字符串常量池在不同的jdk版本有不同的划分,内存的变化也会影响intern方法的执行。

JDK6JDK7及之后
intern()方法会把首次遇到的字符串实例复制到常量池中,并返回此引用会把首次遇到的字符串实例的引用添加到常量池中,并返回此引用
  • Jdk6中常量池位于PermGen(永久代)中,PermGen是一块主要用于存放已加载的类信息和字符串池的大小固定的区域。Jdk6中使用intern()方法的主要问题就在于常量池被保存在PermGen中:首先,PermGen是一块大小固定的区域,一般不同的平台PermGen的默认大小也不相同,大致在32M到96M之间。所以不能对不受控制的运行时字符串(如用户输入信息等)使用intern()方法,否则很有可能会引发PermGen内存溢出;其次String对象保存在Java堆区,Java堆区与PermGen是物理隔离的,因此如果对多个不等值的字符串对象执行intern操作,则会导致内存中存在许多重复的字符串,会造成性能损失。
  • Jdk7将常量池从PermGen区移到了Java堆区,执行intern操作时,如果常量池已经存在该字符串,则直接返回字符串引用,否则复制该字符串对象的引用到常量池中并返回。堆区的大小一般不受限,所以将常量池从PremGen区移到堆区使得常量池的使用不再受限于固定大小。除此之外,位于堆区的常量池中的对象可以被垃圾回收。当常量池中的字符串不再存在指向它的引用时,JVM就会回收该字符串。

实例解析

代码一

String s1 = new String("1"); //常量池中创建"1",堆中创建"1"
s1.intern();          //常量池中已有"1",所以jdk6和jkd7都是返回指向常量池"1"的引用,
                      //但因为该语句没有赋值操作,所以s1仍指向堆中"1"
String s2 = "1";      //s2指向常量池中已存在的"1"
System.out.println(s1==s2);  //s1指向堆中"1",s2指向常量池中"1",false

 jdk6、7、8都返回false

代码二

String s3 = new String("1") + new String("1"); //常量池生成一个"1",堆生成一个"11"
                                               //s3指向堆中"11"
                                       //中间还有2个匿名的new String("1")暂不讨论
s3.intern();             //因为常量池中不存在"11",
                         //jdk6会将堆中"11"复制到常量池中,
                         //jdk7则将堆中"11"的引用添加到常量池中,
                         //此时s3仍指向堆中"11"
String s4 = "11";        //因为常量池中已存在"11"或其引用,s4指向常量池中"11"
System.out.println(s3==s4);  //jdk6中,s4指向常量池中"11",s3指向堆中"11",false
                             //jdk7中,s4指向常量池中指向堆中"11"的引用,true

 在jdk6中返回false,jdk7及以上返回true

适用场景

Jdk6 中常量池位于PremGen区,大小受限,不建议使用String.intern()方法,不过Jdk7 将常量池移到了Java堆区,大小可控,可以重新考虑使用String.intern()方法。

intern()方法优点:执行速度非常快,直接使用==进行比较要比使用equals()方法快很多;内存占用少。虽然intern()方法的优点看上去很诱人,但由于intern()操作每次都需要与常量池中的数据进行比较以查看常量池中是否存在等值数据,同时JVM需要确保常量池中的数据的唯一性,这就涉及到加锁机制,这些操作都是有需要占用CPU时间的,所以如果进行intern操作的是大量不会被重复利用的String的话,则有点得不偿失。由此可见,String.intern()主要 适用于只有有限值,并且这些有限值会被重复利用的场景,如数据库表中的列名、人的姓氏、编码类型等。

String类中的intern()方法
菩提小猿的博客
06-06 4102
1.前言         其实,促使我写这篇博客的原因说起来就挺可笑的。疫情在家,无所事事,就和室友对于专业方面的知识互相吹牛皮。然后,室友出了好几道题考我。也许结果早就在他的意料之中吧。其中,最让我不解的是这道题: String s1 = new String("a") + new String("bc"); s1.intern(); String s2 = "abc"; System.out.println(s1 == s2
String中的intern()方法
Longstar_L的博客
06-26 437
String中的intern方法的实现原理(jdk8中): 以下面代码为例 public class InternTest{ String s1 = new String("a") + new String("b"); s1.intern(); String s2 = "ab"; System.out.println(s1 == s2);//true } (1)String s1 = new String(“a”) + new String(“b”); ①创建StringBuilder对
String.intern(),String.subString()
run bird 的专栏
07-08 640
JDK中对String.intern()方法的解释如下: public String intern() 返回字符串对象的规范化表示形式。 一个初始为空的字符串池,它由类 String 私有地维护。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到
String.intern()方法
qq_52420843的博客
12-10 74
String.intern方法使用
JAVA基础:正则表达式,Stringintern方法StringBuilder可变字符串特点与应用,+连接字符串特点
最新发布
weixin_53755148的博客
09-18 1193
将字符串按照指定的内容进行分割,将分割成的每一个子部分组成一个数组分割内容不会出现在数组中实际上该方法不是按照指定的简单的符号进行分割的,而是按照正则表达式进行分割。
String.intern()
迷失在代码的海洋里
04-13 3283
对于String.intern()清楚以下几点便能完全理解其作用: 1,new String都是在堆上创建字符串对象。当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringTable维护),并返回指向该常量的引用(内存地址)。 调用str1.intern(),编译器会将"abc"字符串添加到常量池中,并返回指向该常量的引用。此后再调用str2.intern(),因常量池中已有"abc"存在,因此就直接返回常量池中的"abc"的引用。 2,通过字面量赋值创建字符串(如:S
java-String中的 intern方法
s1314bin的专栏
01-27 3112
1. 首先String不属于8种基本数据类型,String是一个对象。 因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。 2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null; 3. String str=”kvill”; String str=new String
Stringintern()方法详解
qq_48157004的博客
10-16 994
在开发过程中很多朋友,由于不会正确使用intern(),导致开发的程序,执行效率比较差。同时最近发现一道非常有意思的关于intern()的面试题,这道面试题还是有不小的难度,相信很多朋友看到以后也不知道怎么解答,所以今天咱们深入详解下intern()。当调用intern()时,如果池子里已经包含了一个与这个String对象相等的字符串,正如equals(Object)方法所确定的,那么池子里的字符串会被返回。否则,这个String对象被添加到池中,并返回这个String对象的引用。
StringIntern方法
m0_37210184的博客
04-28 171
引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String。这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念。常量池就类似一个JAVA系统级别提供的缓存。8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊。它的主要使用方法有两种:· 直接使用双引号声明出来的String对象会直接存储在常量池中。· 如果不是用双引号声明的String对象,...
string intern
08-16
- *1* [Stringintern()方法浅析](https://blog.csdn.net/tianyuzui6/article/details/124417267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_...
JVM内存结构之浅析常量池、运行时常量池、StringTable
cd546566850的博客
04-07 1693
介绍前先放一张JVM的内存结构1.6和1.8版本的各组成部分存放位置的模型图 注:以下的分析都是以jdk1.8版本为例 一、常量池、运行时常量池、字符串池 1、常量池:就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息,我们可以通过Javap -v 类名.class 指令反编译一个简单的程序看到如下的常量池信息 2、运行时常量池:常量...
浅析Java内存模型与垃圾回收
09-02
运行时可以添加新的常量,例如通过`String`的`intern()`方法。 接下来,我们讨论垃圾回收。垃圾回收的主要任务是识别并释放那些不再使用的对象所占用的内存,以防止内存泄漏。 **垃圾对象的确定**: 主要有两种...
JVM内存结构浅析
zhaozheng7758的专栏
02-28 9540
内存作为系统中重要的资源,对于系统稳定运行和高效运行起到了关键的作用,Java和C之类的语言不同,不需要开发人员来分配内存和回收内存,而是由JVM来管理对象内存的分配以及对象内存的回收(又称为垃圾回收、GC),这对于开发人员来说确实大大降低了编写程序的难度,但带来的一个副作用就是,当系统运行过程中出现JVM抛出的内存异常(例如OutOfMemoryError)的时候,很难知道原因是什么,另外一方面
Android应用程序包解析过程浅析
热门推荐
freeCode
04-10 1万+
我在上一篇文件中Android应用程序安装过程浅析粗略分析了一下Android应用程序安装过程,其中有一步说到了apk包的解析,但是没有详细分析,这里我们就来粗略分析一下包的解析过程。流程图执行过程       从上面的流程图可以看到,包的解析过程比安装过程执行步骤少很多,也简单一点。那我们就来详细的一步一步的进行剖析一下,我们从外部调用该方法开始分析:private void installPac
StringIntern()方法,详解字符串常量池!
qq_43842093的博客
03-05 2829
字符串拼接最好使用StringBuilder调用append来拼接。使用加号“+”拼接,会new一个StringBuilder,并且在最后调用toString方法时还会new String()。内存中由于创建了较多的StringBuilder和String对象,还有一方面是内存占用,调用GC还会额外花费时间。所以,字符串拼接直接使用StringBuilder会大大提高性能,尤其是多个字符串拼接。
深入解析javaString类的intern方法
赶路人儿
10-21 618
JAVA 语言中有8中基本类型和一种比较特殊的类型String。这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念。常量池就类似一个JAVA系统级别提供的缓存。 8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊。它的主要使用方法有两种: 直接使用双引号声明出来的String对象会直接存储在常量池中。 如果不是用双引号声明的String对象,可以使用String提供的intern方法intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就
Stringintern()方法
Pluto
12-09 165
在1.6及其之前的版本中,intern是先判断字符串常量是否在字符串常量池中,如果存在直接返回该常量,如果没找到,则将该字符串常量加入到字符串常量池,也就是在字符串常量区建立该常量。 在1.7及其之后的版本中,intern是先判断字符串常量是否在字符串常量池中,如果存在直接返回该常量,如果没找到,则把该字符串对象的引用加入到字符串常量池中(实际该常量还在堆中)。 总结,这两个版本的主要区别就是字符串常量池保存的是对象还是对象的引用。 String s1 = new String("a") +.
Stringintern方法
weixin_38568503的博客
03-03 1012
intern方法作用:简单总结就是:有,直接引用,没有,新建加入。 在我们使用System.out.中的System类的时候,就默认加载了Version类 考点:是否读过这些经典书
谈谈String.intern方法
weixin_45671242的博客
07-06 8679
1. 首先明确什么是intern()方法String.intern()是一个Native方法,底层调用C++的 StringTable::intern方法实现。当通过语句str.intern()调用intern()方法后,JVM 就会在当前类的常量池中查找是否存在与str等值的String,若存在,则直接返回常量池中相应Strnig的引用;若不存在,则会在常量池中创建一个等值的String,然后返回这个String在常量池中的引用。 2. intern()方法在jdk6和jdk(7/8)的区别 (1)在
写文章

热门文章

  • String的intern()方法浅析 13316
  • 汇编中有符号数加减计算的补码解释 3049
  • Python导入导出excel 2061
  • Postman/Apifox接口测试——Pre-request自动登录 1972
  • Fastjson、JSON、JSONObject、String 1947

分类专栏

  • 测试开发 1篇
  • java 2篇
  • 学习笔记 5篇
  • 前端 1篇
  • MySQL 1篇
  • 大数据 1篇
  • spark 2篇
  • 唯品会OSP 2篇
  • JVM 2篇
  • 数据仓库 1篇
  • leetcode 20篇
  • docker 1篇
  • excel 2篇
  • 并发
  • xv6 2篇
  • Stata 1篇
  • 汇编 1篇

最新评论

  • String的intern()方法浅析

    未来已来2022: 终于看明白了

  • String的intern()方法浅析

    skr11: 我是true

  • String的intern()方法浅析

    qq_43409416: 通透,很牛比

  • String的intern()方法浅析

    TheCold: System.out.println(s3==s4); 在jdk1.8中测试为false

  • 力扣206——反转链表

    water___Wang: 不错,666,加油~

最新文章

  • Postman/Apifox接口测试——Pre-request自动登录
  • java for循环语句
  • Fastjson、JSON、JSONObject、String
2022年16篇
2021年19篇
2019年4篇

目录

目录

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家供应玻璃钢动物雕塑商场美陈比赛方案南京玻璃钢雕塑北京大型商场创意商业美陈制作大型不锈钢玻璃钢卡通雕塑厂商场美陈吊装方法河南通道商场美陈哪里买玻璃钢小品小龙虾雕塑厂家南宁特色玻璃钢雕塑南阳玻璃钢卡通雕塑制作厂家江苏特色商场美陈有哪些淮安东安玻璃钢雕塑加工厂家山东商场美陈时尚女郎雕塑花朵玻璃钢卡通雕塑定制厂家湖州定制玻璃钢雕塑优势常州百货商场美陈仿玉玻璃钢抽象雕塑造型浙江室内商场美陈供应商吴鑫玻璃钢雕塑怎么分辨是不是玻璃钢雕塑宣武区方形玻璃钢花盆玻璃钢芭蕾舞女孩雕塑深圳led发光玻璃钢雕塑东莞玻璃钢透光雕塑现货青岛卡通玻璃钢雕塑定做焦作学校校园玻璃钢景观雕塑常用玻璃钢雕塑摆件厂家直销党建文化玻璃钢人物雕塑制作莆田玻璃钢雕塑价格山东园林玻璃钢雕塑加工香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化