对于创建String对象的机制,在这一过程中涉及的东西还是值得探究一番的。

  首先看通过new String对象和直接赋值的方式有什么区别,看如下代码:

public static void main(String[] args) {String str1 = new String("abc");String str2 = "abc";String str3 = new String("abc");String str4 = "abc";System.out.println(str1 == str2);System.out.println(str1 == str3);System.out.println(str2 == str3);System.out.println(str2 == str4);
}        

  结果是:false false false true

  我们知道 == 比较的是对象的引用,从代码以及结果可以看出来这段程序中只有三个对象,str1指向一个对象,str3指向一个对象,str2和str4共同指向一个对象。可是到这里有的同学就会迷惑了,我们知道在java中String类是被final修饰的是不可改变的应该每次都会重新生成一个对象啊。可是在这里对象内容都是"abc",所以程序本身也没有发生改变。如果发生改变也不一定会重新生成对象。这都和string机制中的字符串缓冲池有关系。

  当用new的方法创建一个string对象时会先在字符串缓冲池中找有没有和新创建的字符串内容相等的对象,如果没有的话就会在缓冲池新创建一个字符串对象然后再在堆中创建字符串对象,如果缓冲池中已经有了和新创建的字符串内容相等的对象就会直接在堆上新创建对象。如果不用new的方式也是先会看缓冲池中有没有创建过这个对象,如果没有创建就在里边创建一个,如果已经创建了 那新声明的引用就会直接指向这个对象。

  所以main方法的第一行是执行的时候发现缓冲池中并没有一个内容是"abc"的对象所以先在缓冲池中为创建了一个对象内容是"abc",然后在堆中又创建了一个对象。执行到第二行的时候依然会想去缓冲池中找有没有内容是"abc"的字符串对象,发现已经有了。因为他不用在堆上创建对象所以直接把str2指向缓冲池中的对象。第三行一样的道理缓冲池中已经有了所以直接在堆上新建一个就好了。第四行和第二行一样。所以就出现了false false false true的结果。

  再用一段代码验证一下:

public static void main(String[] args) {String str1 = new String("abc");String str2 = "abc";String str3 = new String("abc");System.out.println(str1 == str2.intern());System.out.println(str1 == str3.intern());System.out.println(str2 == str3.intern());System.out.println(str2 == str1.intern());
}

  结果:false false true true

  首先intern()方法:

  public String intern()返回字符串对象的规范化表示形式。(这句话到底啥意思我也不太清楚)
  当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。 它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

  也就是说intern()方法返回的字符串对象肯定是池中的对象而且字符串内容和调用该方法的对象的内容一样。那么结果是false false true true也就不难理解了。str3.intern()和str1.intern()返回的对象就是str2所指向的对象呀。所以我们的结论也得以验证。

  在补充一点关于字符串拼接时的情况:

public static void main(String[] args) {String str1 = "abcd";String str2 = "ab";String str3 = "cd";String str4 = str2 + str3;String str5 = "ab" + "cd";System.out.println(str1 == str4);System.out.println(str1 == str5);
}

  结果:false true

  这时可能就又会迷惑了,哈哈。这就是程序有意思的地方。

  首先说第一个结果是false。str4所指向的对象不应该是缓冲池中的对象吗?讲道理应该是返回true的呀。这就又涉及到字符串拼接的机制了。原来两个字符串str1, str2的拼接首先会调用 String.valueOf(obj),这个Obj为str1,而String.valueOf(Obj)中的实现是return obj == null ? "null" : obj.toString(), 然后产生StringBuilder, 调用的StringBuilder(str1)构造方法, 把StringBuilder初始化,长度为str1.length()+16。此时的StringBuilder对象是在堆上创建的!, 接下来调用StringBuilder.append(str2), 把第二个字符串拼接进去, 然后调用StringBuilder.toString返回结果。所以会返回false。

  而对于第二个结果来说这种拼接方式,jvm会直接把"ab" + "cd" 看成"abcd"。实际上jvm对于这时候的 + (加号)的处理是在编译期就已经完成了。这时候并没有涉及到stringbuilder。

  

java 创建string对象机制 字符串缓冲池 字符串拼接机制相关推荐

  1. java 创建string对象机制 字符串缓冲池 字符串拼接机制 字符串中intern()方法...

    字符串常量池:字符串常量池在方法区中 为了优化空间,为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池.如果字符串已经存在池中,就 ...

  2. java 获取对象方法有哪些方法有哪些方法有哪些_Java中创建String 对象的方法有哪些...

    Java中创建String 对象的方法有哪些 发布时间:2020-11-25 16:45:30 来源:亿速云 阅读:71 作者:Leah 这篇文章将为大家详细讲解有关Java中创建String 对象的 ...

  3. 《C++ Primer 第五版》(第3.5-3.6节) ——C++中的内置数组类型,string对象和C风格字符串

    1.C++中的内置数组类型 C++中的数组是内置数据类型,但不是基础数据类型而是构造数据类型,是有限个相同数据.占据着连续物理存储空间的有序集合.而内置数据类型定义的下标运算符可以处理负值运算(只要在 ...

  4. string对象和C风格字符串

    混用string对象和C风格字符串 我们都知道允许使用字符串字面值来初始化string对象: string s("Hello World!"); C++规定,任何出现字符串字面值的 ...

  5. java中String对象和String变量

    2019独角兽企业重金招聘Python工程师标准>>> java中String对象和String变量 (2011-12-27 20:40:27) 转载▼ 标签: it 最近在论坛上看 ...

  6. [Java基础]String对象的特点(易错点)

    String对象的特点: 1.通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同. 2.以""方式给出的字符串,只要字符串相同(顺序和大小写 ...

  7. Java中String对象的replaceAll方法调用性能优化小技巧

    Java中String对象的replaceAll方法调用性能优化小技巧 0x01 Java中String对象的replaceAll方法调用性能优化小技巧 1.1 What? 1.2 Why? 1.3 ...

  8. java中String对象作为参数传递问题

    问题 java中将对象作为参数传递究竟是值传递还是引用传递? 1.基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的. 2.对象作为参数传递时,是把对象在内存中的地址拷贝 ...

  9. Java创建JSON对象

    Java创建JSON对象 private void getJson(HttpServletRequest request, HttpServletResponse response)throws Se ...

最新文章

  1. eclipse插件之easyshell
  2. VSTO Office二次开发PPTRibbonX命令操作及对象添加
  3. 属性文件有一个多行值
  4. android dns解析
  5. 像素包装:在内存中并不以紧密形式排列
  6. S5PV210裸机之SD卡
  7. 做企业:什么都可以外包么
  8. Spring帖子汇总
  9. 基于lucene的案例开发:纵横小说数据库操作
  10. 如何让女性乳房更具吸引力?整形医生可以用眼动追踪技术大显神通吗?
  11. .net(C#) json 大驼峰、小驼峰,命名混用
  12. 极大似然估计、极大似然函数
  13. 计算机管理器802.11n有,802.11n无线网卡驱动
  14. android--email发送邮件,文本还有附件形式的邮件
  15. 细数储层预测过程中碰到的的几类采集脚印
  16. hud抬头显示器哪个好_抬头显示器HUD研究综述
  17. java的各种排序算法的分析及实现
  18. 国手机网民首超6亿 病毒成移动安全一级杀手
  19. BIM技术:带你了解预留洞工法工艺
  20. 重庆“90后”双胞胎“动妹” 守护春运回家路

热门文章

  1. Mac下如何输入全角空格
  2. Don Box博客中文版入驻CSDN,志愿者翻译招募中....
  3. 关于excel中的超长数字显示方法
  4. 求n的阶乘和n的阶乘的和
  5. Excel简单宏定义(快速合并多个表格,合并多个工作表,合并特定工作表)
  6. 利用pearcmd.php本地文件包含(LFI)
  7. SpringCloud-Gateway配置及持久化、过滤器、异常处理
  8. 鸡尾酒疗法(C语言)
  9. MIT6.824环境搭建:wls+vs code
  10. 微信|QQ扫码登录网页版二维码失效问题解决方案 网站无法访问PC网页版如何解决 安卓软件历史版本下载 FV fooview悬浮球帮助教程