最近在工作的时候,一句再正常不过的代码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。

java 字符串驻留_Java中的字符串驻留相关推荐

  1. java字符连接字符串数组_Java中连接字符串的最佳方法

    java字符连接字符串数组 最近有人问我这个问题–在Java中使用+运算符连接字符串是否对性能不利? 这让我开始思考Java中连接字符串的不同方法,以及它们如何相互对抗. 这些是我要研究的方法: 使用 ...

  2. java字符串转字符串列表_Java中的字符串列表示例

    java字符串转字符串列表 We have to read total number string i.e. "n", create a list of the Strings a ...

  3. java字符截取_java中截取字符串方法

    Java 简介 substring public String substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串.该子字符串始于指定索引处的字符,一直 ...

  4. java 字符串 判断_Java中判断字符串是否相等的实现

    在最近的开发中,我踩到一个坑,过程是这样的.我需要在Java中判断两个字符串是否相等,按照以往的经历使用 == 双等号的操作符来判断,但是在Java中,这样写却没有实现我想要的效果.经过查阅资料后,把 ...

  5. java字符串长度_Java中String字符串的最大长度?

    1.Java中的字符串String最大长度,编译期如果是javac编译就是65534.如果绕过javac编译的限制,其最大长度可以达到u2类型变达的最大值65535. Oracle JDK的编译工具J ...

  6. java 字符串用法_Java中的字符串用法小结

    本文实例总结了Java中的字符串用法.分享给大家供大家参考.具体分析如下: 字符串的本质是char类型的数组,但在java中,所有用双引号""声明的字符串都是一个String类的对 ...

  7. java定义字符串常量_Java中的字符串常量池

    ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...

  8. java打印字符串引用_Java中的字符串及其中的常用方法

    字符串是由多个字符组成的一串数据 String的特点: 字符串是常量,一旦被创建就不能改变,这是因为字符串的值是存放在方法区的常量池里面,但是引用可以改变.字符串字面值"ab"也可 ...

  9. java获取字符串长度_java中定义字符串String s=”pzhu”,下面操作可以取得字符串长度的是( )。...

    [单选] 施工现场宿舍.办公室等临时用房建筑构件的燃烧性能等级应为():当采用金属夹芯板材时,其芯材的燃烧性能等级应为(). [填空题] <敦煌曲谱>又名(),是933年用燕乐半字谱抄写的 ...

最新文章

  1. 【Network Security!】xrdp+vnc4server+xfce4远程管理Ubuntu服务器桌面
  2. go预防CSRF攻击
  3. MySQL where后面的列子查询使用
  4. linux 下oracle基于raw扩充表空间步骤
  5. 用awk一些常用技巧sort uniq
  6. MobileIron Access保障移动设备的企业云数据安全
  7. 用更少的钱看更清晰的视频——详谈阿里云窄带高清
  8. dhcpd中的mac
  9. DDD开发框架ABP之导航菜单
  10. Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案
  11. Day 35 年会抽奖 + 抄送列表
  12. 在html字符串拼接函数,通过html字符串连接组合并调用javascript函数
  13. system verilog编程题_SystemVerilog通用程序库(下)
  14. TiDB 在中国电信翼支付的大规模深度实践
  15. mysql替换后的zzigu_MySQL导入数据报错Got a packet bigger than‘max_allowed_packet’bytes错误的解决方法...
  16. 相机标定后得到相机视域,并根据相机视域求取摄像机位置和摄像机方位角
  17. 【Elasticsearch】 (搜索引擎如何做搜索推荐?) Elasticsearch中 使用 Suggesters 推荐查询
  18. 一分钟教会你黑白图片如何上色
  19. node.js入门之child_process子进程
  20. 平板电脑win10 android比较好,华为MateBook名不副实!Win10平板电脑最合适

热门文章

  1. 转载(生物分析专题网站(很全、实用))
  2. 火狐Firefox浏览器安装使用油猴Tampermonkey插件
  3. UWB定位matlab代码及详细解析(附github下载链接)
  4. UWB室内定位:TDOA定位方法的时间同步问题
  5. VSRX防火墙安装与部署
  6. 身残志不残-霍金精神
  7. python图片裁剪软件_python 实现图片裁剪小工具
  8. 医保基金稽查案件管理系统丨陀螺研究院×FISCO BCOS案例专辑
  9. Microsoft Intune简介
  10. 天气预报发展简史:从玄学到科学