最近在工作的时候,一句再正常不过的代码String a = “hello” + “world”;被改成了new StringBuilder().append(“hello”).append(“world”);当时就比较疑惑这样做的好处,后来到网上查找了一番之后才清楚这与Java中的字符串驻留机制有关,那么什么是驻留呢?

顾名思义,驻留就是在内存中保留(在Java中,我们通常称驻留对象的地方为驻留池,不过它也是内存的一部分),它不仅存在于认证系统下载站Java中,在C#中同样存在。那么我就写几个例子来讲解什么叫Java中字符串的驻留:

public classtest{public static void main(String[] args) {String a = "abc";String b = "abc";System.out.println(a == b);  // trueString c = new String("abc");System.out.println(a == c);  // falseSystem.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());  // trueSystem.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的地方在哪里。继续往下看。

原因在于使用+连接字符串每次都生成新的对象,而且是在ghost xp系统下载堆内存上进行,而堆内存速度比较慢(相对而言),那么再大量连接字符串时直接+是不可取的,当然需要一种效率高的方法。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);  // trueSystem.out.println(c == e);  // falseSystem.out.println(c == f);  // falseSystem.out.println(d == e);  // falseSystem.out.println(d == f);  // falseSystem.out.println(e == f);  // false}}

c == d输出true,因为c和d都是字符串常量,他们的值在编译时就确定了。而所有涉及到引用的地方都是在运行时才确定值的,所有下面会全部输出为false。

java 字符串驻留_【Java中的字符串驻留】相关推荐

  1. java对字符串归一化_搜索引擎中的字符串归一化 | 学步园

    搜索引擎中对于Q查询,都会涉及到字符串归一化这个步骤,以提高结果召回率.字符串的归一化包括三个方面:繁体转简体:全角字符转半角:大写字母转小写. 建倒排时,会先对字符串做归一化处理,然后再分词取ter ...

  2. 1967. 作为子字符串出现在单词中的字符串数目

    1967. 作为子字符串出现在单词中的字符串数目 给你一个字符串数组 patterns 和一个字符串 word ,统计 patterns 中有多少个字符串是 word 的子字符串.返回字符串数目. 子 ...

  3. Java中string字符串的值_Java中的字符串(String)

    一.基本概念: 字符串是一系列字符串的序列.在Java语言中字符串是用一对对双引号"",括起来的字符系列.例如"Hello","你好".从数 ...

  4. java 判断 中文字符_java中判断字符串中是否有中文字符

    package com.meritit.test; public class TestChart { public static void main(String[] args) throws Exc ...

  5. Java字符串的重要性_java中的字符串相关知识整理

    字符串就是一系列的字符组合的串,如果写过C/C++的应该就了解,在字符串的操作上会有许多操作的函数与类,用于简化代码的开发.一方面是因为字符串在代码中会频繁用到,另一方面是因为字符串的操作非常麻烦. ...

  6. java字符串确定汉字_java中判断字符串中汉字的个数

    使用方法3与方法4时需要注意一些问题,代码中会有注释. 代码如下: package 包名; import java.util.ArrayList; import java.util.regex.Mat ...

  7. java 字符分割函数_java中的字符串分割函数

    Java中的我们可以利用split把字符串按照指定的分割符进行分割,然后返回字符串数组,下面是string.split的用法实例及注意事项: java.lang.string.split split ...

  8. java字符串的拆分_Java中的字符串分割 .

    java中的split函数和js中的split函数不一样. Java中的我们可以利用split把字符串按照指定的分割符进行分割,然后返回字符串数组,下面是string.split的用法实例及注意事项: ...

  9. java集合转字符串拼接_关于集合和字符串的互转实现方法

    今天在写项目的时候遇到一个问题,就是要把得到的一个集合转换成字符串,发现 import org.apache.commons.lang.stringutils; 有这么一个简单的方法:string s ...

  10. python字符串驻留机制_Python中的字符串驻留

    C#中的字符串驻留 熟悉.NET的人都应该知道C#中的字符串驻留机制,.NET维护了一个驻留池,它会把在编译期间就相同的字符串只保留一份拷贝.如果仅在运行期间值才相同的字符串变量,.NET才会为这个2 ...

最新文章

  1. C++自定义Log工具
  2. 从数理统计简史中看正态分布的历史由来
  3. 干货|一文全解深度学习中的卷积
  4. css 样式使用方法的累积
  5. java访问权限 public private protected
  6. The ntpath module
  7. Redis作者摊上事了:多人要求修改Redis主从复制术语master/slave
  8. 计算机程序设计基础试题与答案,2018年4月自考计算机基础与程序设计02275试题及答案.doc...
  9. python我的世界服务器_Python取Minecraft服务器信息
  10. Java多线程系列--“JUC锁”03之 公平锁(一)
  11. pdsh命令控制多台树莓派超爽
  12. openlayers示例教程002:简析EPSG:4326 和 EPSG: 3857
  13. Unity Shader(固定管线着色器)
  14. semilogx 多条曲线_如何在excel中绘制多条曲线
  15. QScrollArea的简单使用
  16. MIMO信道容量仿真MATLAB,mimo系统的信道容量分析及matlab仿真.doc
  17. WINDOWS系统文件夹、实用自带工具、DOS、进程等,解析集合(积累)较实用...
  18. git常用命令之git push使用说明
  19. 滤波电路(上),无源滤波器
  20. 408计算机学科专业基础综合——操作系统

热门文章

  1. 怀旧魔兽最新服务器,魔兽怀旧服:这才是永久60服务器的现状,“真实且残酷”!...
  2. 一个公司采购申请审批系统,包含用户登录注销、用户创建、角色分配、采购申请审批及其他相关功能。
  3. 【渝粤教育】国家开放大学2019年春季 1192高层建筑施工 参考试题
  4. MS Access 教程之 如何解决从 Access 复制到 Excel 太慢问题?
  5. 计算机基础知识中真值是什么,计算机中什么叫机器数,什么叫真值
  6. Typora的初步使用及Markdown语法总结
  7. ckEditor使用方法
  8. Java6 十大新特性
  9. jQuery Mobile-页面跳转
  10. 2021年中国国有企业经营现状分析:营业收入及利润总额均增加[图]