Java中的字符串驻留
转自:http://www.cdtarena.com/javapx/201307/9088.html
最近在工作的时候,一句再正常不过的代码String a = “hello” + “world”;被改成了new StringBuilder().append(“hello”).append(“world”);当时就比较疑惑这样做的好处,后来到网上查找了一番之后才清楚这与Java中的字符串驻留机制有关,那么什么是驻留呢?
顾名思义,驻留就是在内存中保留(在Java中,我们通常称驻留对象的地方为驻留池,不过它也是内存的一部分),它不仅存在于Java中,在C#中同样存在。那么我就写几个例子来讲解什么叫Java中字符串的驻留:
public class test {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
System.out.println(a == b); // true
String c = new String("abc");
System.out.println(a == c); // false
System.out.println(a.equals()); // true
}
}
上面这段代码在执行完String a = “abc”这一句的时候会在内存中创建一个值为abc的String类型对象。当执行下一句代码,即String b = “abc”的时候,java会首先去驻留池里面查找是否有值为abc的字符串对象,如果有就让b引用执行那个对象,如果没有就新创建一个并且将其存放在驻留池中。所以,不难理解,当程序执行到第三句话的时候会返回true,我们知道==在java中比较的是对象的引用指向的对象的内存首地址是否一样,而a和b指向的是同一个对象,所以会返回true。继续往下走,当程序执行到String c = new String(“abc”)这句话的时候,java做的事包括: 检查abc这个字符串对象是否在驻留池中,如果存在就把它当做值,然后再在堆上创建一个String类型的对象放到堆中(我们都知道在java中对象是放在堆中,对象的引用是存放在栈中)。所以这句话其实可能创建了2个对象(如果abc已经在驻留池中了,就只是在堆中创建了一个对象)。同时通过new String()创建出来的字符串对象是不会被放到驻留池中的。你也许会想,有没有一种方法让我把在堆中创建的对象放到驻留池中去呢?答案是有的!java提供了一个方法叫做intern(),如果执行c.intern(),会首先把c指向的对象放到驻留池中,然后返回指向这个对象的引用。那么,以下代码会输出什么呢?
public class test {
public static void main(String[] args) {
String a = "abc";
String b = new String("abc");
System.out.println(a == b.intern()); // true
System.out.println(a == b); // false
}
}
当然是true!不过它的执行过程还是值得说一下的,重点在b.intern();这句话上。经过上面的讲解你也许会想过程应该是首先到堆中创建一个值为abc的String对象,然后将这个对象放到驻留池中。那么如果驻留池中已经存在值为abc的字符串对象了呢?那么b.intern会直接返回驻留池中的对象,所以这里会返回true。继续向下执行,System.out.println(a == b);会返回false,因为在执行b.intern();这句话的时候,实际上是直接返回了驻留池中的对象,所以对原本b指向的堆中的对象没有影响,所以a == b会返回false。
我通过上面这个例子简单讲解了java中的字符串驻留,那么现在回到文章开始部分的疑惑去,为什么使用StringBuilder而不是简单地使用”+”来连接字符串呢?经过上面的讲解,你可能会猜测StringBuilder用了字符串驻留,而”+”不是。恭喜你,你答对了,加10分。但是你也许并不知道使用”+”的时候tricky的地方在哪里。继续往下看。
原因在于使用+连接字符串每次都生成新的对象,而且是在堆内存上进行,而堆内存速度比较慢(相对而言),那么再大量连接字符串时直接+是不可取的,当然需要一种效率高的方法。Java提供的StringBuffer和StringBuilder就是解决这个问题的。区别是前者是线程安全的而后者是非线程安全的。所以促使我写这篇博客的问题的原因就找到了。此外,值得注意的一点是,驻留池是不会被GC回收的,它会在程序运行期间一直保留。
最后我还想再说点题外话,请看下面这段程序:
public class test {
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = "ab";
String d = "a" + "b";
String e = a + "b";
String f = a + b;
System.out.println(c == d); // true
System.out.println(c == e); // false
System.out.println(c == f); // false
System.out.println(d == e); // false
System.out.println(d == f); // false
System.out.println(e == f); // false
}
}
c == d输出true,因为c和d都是字符串常量,他们的值在编译时就确定了。而所有涉及到引用的地方都是在运行时才确定值的,所有下面会全部输出为false。
转载于:https://blog.51cto.com/daimasd/1242338
Java中的字符串驻留相关推荐
- java 字符串驻留_【Java中的字符串驻留】
最近在工作的时候,一句再正常不过的代码String a = "hello" + "world";被改成了new StringBuilder().append(& ...
- java 字符串驻留_Java中的字符串驻留
最近在工作的时候,一句再正常不过的代码String a = "hello" + "world";被改成了new StringBuilder().append(& ...
- Python中的字符串驻留
C#中的字符串驻留 熟悉.NET的人都应该知道C#中的字符串驻留机制,.NET维护了一个驻留池,它会把在编译期间就相同的字符串只保留一份拷贝.如果仅在运行期间值才相同的字符串变量,.NET不会为这个2 ...
- python字符串驻留机制_Python中的字符串驻留
C#中的字符串驻留 熟悉.NET的人都应该知道C#中的字符串驻留机制,.NET维护了一个驻留池,它会把在编译期间就相同的字符串只保留一份拷贝.如果仅在运行期间值才相同的字符串变量,.NET才会为这个2 ...
- 检查Java中的字符串是空还是空[重复]
本文翻译自:Checking if a string is empty or null in Java [duplicate] This question already has an answer ...
- java oracle 连接字符串函数_通过shell来比较oracle和java中的字符串使用
这些准备工作齐了之后,我们来从Java中的字符串使用入手来比较一下oracle中对于字符串的处理. java中有如下的一些函数,我会依次来做比较. public char charAt(int ind ...
- 图说:为什么Java中的字符串被定义为不可变的
转载自 图说:为什么Java中的字符串被定义为不可变的 字符串,想必大家最熟悉不过了,通常我们在代码中有几种方式可以创建字符串,比如:String s = "Hollis";这时, ...
- Java中连接字符串的最佳方法
最近有人问我这个问题–在Java中使用+运算符连接字符串是否对性能不利? 这让我开始思考Java中连接字符串的不同方法,以及它们如何相互对抗. 这些是我要研究的方法: 使用+运算符 使用StringB ...
- java 匹配最后一次出现的字符_在Java中查找字符串中字符的最后一次出现
使用该lastIndexOf()方法在Java中查找字符串中字符的最后一次出现. 假设以下是我们的字符串.String myStr = "Amit Diwan"; 在上面的字符串中 ...
最新文章
- SQL 2008中修改表结构提示“阻止保存要求重新创建表的更改”
- Grafana关键表结构分析
- JavaScript编程:文档对象模型DOM
- Webex远程网络视频会议使用指南
- 服务器保存excel文件慢,从使用IE的服务器缓慢地保存Excel文件
- 圈钱跑路 ERC20 Token 合约代码分析
- CSS过渡属性transitions详细解读——Web前端系列学习笔记
- 西南科技计算机在线自测,西南科技大学2017春季第一学期高等数学1在线自测答案...
- 安装Windows7出现:”安装程序无法创建新的系统分区 也无法定位系统分区“ 终极解决方案...
- python内存池_python内存监控工具memory_profiler和guppy的用法详解
- SecureCRT key登录linux ssh设置
- 080 HBase的属性
- media encoder中文2022已上线
- 配置百度云CDN加速
- Unity3D自动寻路之Nav Mesh Agent(导航网格代理)
- 七牛云对象存储实现文件的上传与下载
- web前端面试题【html+css+js+框架】
- FTP下载工具的使用
- signature=d392c0d1876b3909bd8f7e1f3c0bef22,【技术分享】NSA武器库:CVE-2017-9073 EsteemAudit分析...
- 改oracle sockets,安装GI最后检查时出现warning - Domain Sockets,PRVG-11750
热门文章
- YOLO学习-3:ubuntu16.04+ yolov3(darknet)+GPU(nvidia 1080ti)+opencv2.4.11 摄像头测试实践
- Cadence IC CDB-OA工艺库转换方法
- java 登录 https_java – 如何在Web应用程序中实现HTTPS登录页面?
- matlab 仿真模型,MATLAB Simulink 仿真
- 位掩码(BitMask)
- 工业用微型计算机(21)-指令系统(17)
- 【推荐系统】推荐系统里,你是怎么Embedding的?
- 【数据竞赛】组合特征的构建技巧,如何快速构建百大组合特征池
- 【Python基础】101道Numpy、Pandas练习题,提升你的Python水平
- 【特征工程】17种将离散特征转化为数字特征的方法