这个问题可以说是一个高频的面试题目,以前把这个问题弄懂了,最近突然想到这个问题,一时间竟然没有太好的思路了。所以花些时间整理一下其中的知识点。

一、内存分配策略

我们先来看一个题目(这个问题都快看吐了~),你知道正确的运行结果并给出解释吗。不知道也没关系,我会在下面给出具体的分析。

    @Testpublic void test() {String s1 = "abc";String s2 = "abc";String s3 = new String("abc");String s4 = new String("abc");System.out.println(s1 == s2);     // trueSystem.out.println(s3 == s4);     // falseSystem.out.println(s1 == s3);     // false}

String s = ""String s = new String("") 两种方式都可以创建字符串对象,它们有什么不同吗。下面的解释会涉及到 java 虚拟机内存区域 方面的知识,不知道的同学可以先了解一下。

1.1 创建对象的方式

String s = "abc" 方式创建的对象,存储在字符串常量池中,在创建字符串对象之前,会先在常量池中检查是否存在 abc 对象。如果存在,则直接返回常量池中 abc对象的引用,不存在会创建该对象,并将该对象的引用返回给对象 s

以 HotSpot 虚拟机为例,在 jdk1.8 之前,字符串常量池在方法区中,为了减小方法区内存溢出的风险,在 jdk1.8 之后就把字符串常量池转移到 java 堆中了。

String s = new String("abc") 这种方式,实际上 abc 本身就是字符串池中的一个对象,在运行 new String() 时,把字符串常量池中的字符串 abc 复制到堆中,因此该方式不仅会在堆中,还会在常量池中创建 abc 字符串对象。 最后把 java 堆中对象的引用返回给 s

1.2 问题分析

通过上面的分析,大家应该对问题结果有一个感性的认识了。

s1 指向字符串常量池中的 abc 对象,s2 也指向字符串常量池中的 abc 对象,因此 s1s2 指向的是同一个对象,故 s1 == s2 返回 true

s3s4 分别指向 java 堆中两个不同的对象,因此 s3 == s4false

s1s3 分别指向字符串常量池中的对象与 java 堆中的对象,s1 == s3 返回值也是 false

二、问题扩展

上面的问题清楚了原理还很好理解,下面还有一个例子,理解起来就不那么容易了。

    @Testpublic void test() {String s1 = "abc";String s2 = "a";System.out.println(s1 == ("a" + "bc"));    // trueSystem.out.println(s1 == (s2 + "bc"));     // false }

2.1 字符串常量重载 "+"

"a" + "bc" 是两个字符串常量的拼接,当一个字符串由多个字符串常量连接而成时,它自己也肯定是字符串常量。java 虚拟机对于字符串常量的 “+” 号连接,在程序编译期,java 虚拟机就将常量字符串的 “+” 连接优化为连接后的值。

这样一来,最终只会在常量池中创建一个 abc 对象,并没有创建临时字符串对象 abc,减轻了垃圾收集器的压力。s1 == ("a" + "bc"),因为 abcs1) 在字符串常量池中已经存在了,因此返回值是 true

2.2 字符串引用重载 "+"

java 虚拟机对于有字符串引用存在的字符串连接,即 s2 + "bc" 在被编译器执行的时候,会自动引入 StringBuilder 对象,调用其 append() 方法,最终调用 toString() 方法返回其在堆中对象的引用。 下面是反编译后的部分字节码。

因此 s2 + "bc" 就等同于下面过程。

s2 + "bc" = new StringBuilder().append(s2).append("bc").toString();

s1 == (s2 + "bc") 在进行比较时,s1 是字符串常量池中对象的引用,(s2 + "bc") 则是 java 堆中一个对象的引用,因此返回值是 false。为什么说 s2 + "bc" 返回的是堆中对象的引用呢,只要到 StringBuilder 源码中查看一下 toString() 就能理解了。

   /*** StringBuilder 类的 toSTring() 方法*/@Overridepublic String toString() {// Create a copy, don't share the arrayreturn new String(value, 0, count);}

三、参考资料

  • String 对象内存分配 (常量池和堆的分配)
  • Java—String 字符串运算符"+"重载分析

String 对象内存分配策略相关推荐

  1. java内存模型 创建类_JVM内存模型及String对象内存分配

    昨天看了一篇关于<Java后端程序员1年工作经验总结>的文章,其中有一段关于String和StringBuffer的描述,对于执行结果仍然把握不准,趁此机会也总结了下JVM内存模型. 1. ...

  2. JVM学习笔记之-堆,年轻代与老年代,对象分配过程,Minor GC、Major GC、Full GC,堆内存大小与OOM,堆空间分代,内存分配策略,对象分配内存,小结堆空间,逃逸分析,常用调优工具

    堆的核心概述 概述 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域.Java堆区在JVM 启动的时候即被创建,其空间大小也就确定了.是JVM管理的最大一块内存空间. 堆内存的大小是可 ...

  3. 《深入理解Java虚拟机》-----第3章 垃圾收集器与内存分配策略

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来. 3.1 概述 说起垃圾收集(Garbage Collection,G ...

  4. 垃圾收集器与内存分配策略(五)之垃圾日志与常见参数

    2019独角兽企业重金招聘Python工程师标准>>> 垃圾收集器与内存分配策略(五)--垃圾日志与常见参数 理解GC日志 每个收集器的日志格式都可以不一样,但各个每个收集器的日志都 ...

  5. jvm(3)-垃圾收集器与内存分配策略

    [0]README 0.1)本文部分文字转自:深入理解jvm,旨在学习 垃圾收集器与内存分配策略 的基础知识: [1]垃圾回收概述 1)GC(Garbage Collection)需要完成的3件事情: ...

  6. JVM内存管理:深入垃圾收集器与内存分配策略

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...

  7. java_opts gc回收器_jvm垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略: 以下参考周志明的<>. 判断对象是否存活: 引用计数:通过判断对象被引用的次数(为0,则表示不可被使用),但这很难解决对象相互循环引用的问题. 根搜索算法:即采 ...

  8. 【转】JVM内存管理:深入垃圾收集器与内存分配策略

    2019独角兽企业重金招聘Python工程师标准>>> Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收 ...

  9. jvm垃圾收集器与内存分配策略

    2019独角兽企业重金招聘Python工程师标准>>> 垃圾收集器与内存分配策略: 以下参考周志明的<<深入理解jvm高级特性与最佳实践>>. 判断对象是否存 ...

最新文章

  1. 密码生成常见的编码规则
  2. C# 拖放操作源码详解2
  3. python pynlpir中科院分词的使用
  4. Chuck Cobb谈敏捷组织中PMO的角色
  5. 如何离线安装chrome插件
  6. 商务英语计算机,BEC商务英语
  7. 图的简单应用(C/C++实现)
  8. 亚马逊首席科学家:揭秘 Alexa 语音识别技术|AI NEXT
  9. 算法竞赛入门经典训练指南
  10. GridView的多表头(排序)实例方法
  11. cpt怎么转换成HTML,Excel直接转成模板cpt
  12. 盘口功夫——研判股价启动前的四种征兆----
  13. DAC0832的多功能信号/波形发生器Proteus仿真设计,4种波形(正弦、三角、方波、锯齿),附仿真+C程序+论文等
  14. 删除右键菜单中的 “上传到wps云文档”
  15. 探寻埋藏在心底的梦想,社科院与杜兰大学金融管理硕士项目伴你同行
  16. 点击扫一扫二维码返回文本内容
  17. 概率论笔记3.1二维随机变量及其函数分布
  18. 微服务拆分策略和原则
  19. 如何查询期刊的中科院分区
  20. java 一个线程占多少内存_一个jvm线程占用多少操作系统内存

热门文章

  1. Error creating bean with name ‘org.springframework.security.oauth2.config.annotation.web.configurati
  2. 设计模式——装饰者(Decorator)模式DEMO——成绩汇报的装饰者模式实现
  3. Python——OpenCV(opencv-python库)调用摄像头
  4. HMTL/CSS——下拉菜单DEMO
  5. Nearest Interesting Number
  6. Maximal Continuous Rest
  7. Superhero Transformation
  8. Hive 0.12.0安装配置
  9. Python基础day08 作业解析【7道 面向对象题目】
  10. 关于Android 中 一个错误的解决办法 “Do not request Window.FEATURE_ACTION_BAR.....