揭秘:Java字符串对象的内存分布原理
先来看看下面寄到关于String的真实面试题,看看你废不废?

String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
String str4 = new String("Hello");System.out.println(str1 == str2); // true or false?
System.out.println(str1.equals(str2)); // true or false?
System.out.println(str1 == str3); // true or false?
System.out.println(str1.equals(str3)); // true or false?
System.out.println(str3 == str4); // true or false?
如果要正确回答上面几个面试题,不深入理解String类型的内存原理是不行的,本篇的唯一目的就是言简意赅、深入浅出的梳理String类型的底层原理。
一,字符串存储的内存原理
1,字面量声明字符串对象
String name = "Java";
如上,以字面量声明的字符串String对象存储在堆内存中,而其内容(字符数组)则保存在字符串常量池中(从JDK 7开始,字符串常量池被移到了堆中)。

结合上图,对于代码String name = "Java";,创建的字符串对象的内存分布如下:
- ①
String是引用类型,所以变量name存储的是字符串对象的地址值0xefd,指向常量池某一条记录,如箭头① - ②常量池是HashTable,存储的是字符串对象的地址,如箭头②
- ③String内部使用一个名为
value的byte数组存储字符串的,显然变量value是引用类型,所以其值也是地址,指向一个byte数组对象,如上图箭头③

那么问题来了,两个字面量相等的变量的内存分布是怎样的呢?
String name = "Java";
String name2 = "Java";

当创建一个String时,如果该字符串已经存在于常量池中,则直接引用该字符串;否则,会在常量池中创建一个新的字符串实例,并返回对该实例的引用。
所以,如上图所示,因为这两个变量都是以字面量声明的,且字符串值都是“Java”,所以变量name和name2会指向同一个地址。
2,构造函数声明字符串对象
String name = new String("Java");
如上,当以构造函数声明字符串对象时,与字面量最大的不同是,创建的字符串对象不会保存在字符串常量池中,字符串String对象存储在堆内存中,其内存分布如下图所示:

类似的问题,创建两个值一样的对象,其内存是怎么分布的呢?
String name = new String("Java");
String name2 = new String("Java");
对于上面代码,如下图所示,会创建两个完全不同的字符串对象。

从上面可以看出,用字面量声明对象,字符串相同时,可以复用字符串对象,有更高的内存利用率。所以,最佳实践是使用字面量声明字符串对象。
二,面试题分析
对于文章开头的面试题:
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
String str4 = new String("Hello");System.out.println(str1 == str2); // true or false?
System.out.println(str1.equals(str2)); // true or false?
System.out.println(str1 == str3); // true or false?
System.out.println(str1.equals(str3)); // true or false?
System.out.println(str3 == str4); // true or false?
①
对象str1和str2是通过字面量创建的,这两个变量在字符串常量池的作用下,指向同一个字符串对象,所以:
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
结果都是true:

这里需要知道运算符 == 和 函数equals的区别:
- 运算符
==比较的是两个对象在内存中地址,即栈中变量存储的值 - 函数
equals会把内存中的字符串值取出来比较是否相同,如上例,比较的是字符串"Java"和"Java"是否相同
②
变量str3是通过构造函数创建的,所以不会通过常量池复用已经创建的对象,所以两个变量指向不同地址的对象,用运算符==比较的结果是false;但两个对象存储的字符串内容是相同的,用equals比较的结果是true:
System.out.println(str1 == str3);
System.out.println(str1.equals(str3));

③
System.out.println(str3 == str4);
System.out.println(str3.equals(str4));
因为对象str3和str4都是通过构造函数创建的,根据前面的分析,会创建两个不同的对象,所以,用运算符==比较的结果是false;但两个对象存储的字符串内容是相同的,用equals比较的结果是true:

相关文章:
揭秘:Java字符串对象的内存分布原理
先来看看下面寄到关于String的真实面试题,看看你废不废? String str1 "Hello"; String str2 "Hello"; String str3 new String("Hello"); String str4 new String("Hello");System.out.println(str1 str2)…...
Vue.js - 生命周期与工程化开发【0基础向 Vue 基础学习】
文章目录 Vue 的生命周期Vue 生命周期的四个阶段Vue 生命周期函数(钩子函数 工程化开发 & 脚手架 Vue CLI**开发 Vue 的两种方式:**脚手架目录文件介绍项目运行流程组件化开发 & 根组件App.vue 文件(单文件组件)的三个组成…...
Element-UI 快速入门指南
Element-UI 快速入门指南 Element-UI 是一套基于 Vue.js 的桌面端组件库,由饿了么前端团队开发和维护。它提供了丰富的 UI 组件,帮助开发者快速构建美观、响应式的用户界面。本篇文章将详细介绍 Element-UI 的安装、配置和常用组件的使用方法,帮助你快速上手并应用于实际项…...
2024华为OD机试真题-整型数组按个位值排序-C++(C卷D卷)
题目描述 给定一个非空数组(列表),其元素数据类型为整型,请按照数组元素十进制最低位从小到大进行排序, 十进制最低位相同的元素,相对位置保持不变。 当数组元素为负值时,十进制最低位等同于去除符号位后对应十进制值最低位。 输入描述 给定一个非空数组,其元素数据类型…...
善听提醒遵循易经原则。世界大同只此一路。
如果说前路是一个大深坑,那必然是你之前做的事情做的不太好,当坏的时候,坏的结果来的时候,是因为你之前的行为,你也就不会再纠结了,会如何走出这个困境,是好的来了,不骄不躁…...
CrossOver有些软件安装不了 用CrossOver安装软件后如何运行
CrossOver为用户提供了三种下载软件的方式分别是:搜索、查找分类、导入。如果【搜索】和【查找分类】提供的安装资源不能成功安装软件,那么我们可以通过多种渠道下载安装包,并将安装包以导入的方式进行安装。这里我们以QQ游戏为例,…...
在vue中如何使用leaflet图层展示地图
在vue中如何使用leaflet <template><div id"map" class"map"></div> </template><script> export default {data () {return {};},mounted(){this.initMaps()},methods: {initMaps () {const map L.map(map, {zoomControl…...
mybatisplus 字段存的是json 在查询的时候怎么映射成对象
数据库交互对象 TableName(value "表名", autoResultMap true)TableField(typeHandler JacksonTypeHandler.class, value "user_info")private User user;autoResultMap 是一个 MyBatis-Plus 中的注解属性,用于控制是否自动生成结果映射。…...
Python 学习笔记【1】
此笔记仅适用于有任一编程语言基础,且对面向对象有一定了解者观看 文章目录 数据类型字面量数字类型数据容器字符串列表元组 type()方法数据类型强转 注释单行注释多行注释 输出基本输出连续输出,中间用“,”分隔更复杂的输出格式 变量定义del方法 标识符…...
Git系列:rev-parse 使用技巧
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
【Java数据结构】详解LinkedList与链表(一)
🔒文章目录: 1.❤️❤️前言~🥳🎉🎉🎉 2.ArrayList的缺陷 3.链表的概念及结构 4.无头单向非循环链表的实现 4.1成员属性 4.2成员方法 createList display——打印链表 addFirst——头插 addLast…...
PDF高效编辑器革新:一键智能转换PDF至HTML,轻松开启文件处理全新时代!
信息爆炸的时代,PDF文件因其跨平台、不易修改的特性,成为了商务、教育、出版等领域不可或缺的文件格式。然而,PDF文件的固定性也带来了诸多不便,特别是在需要对其内容进行编辑或格式转换时。这时,一款高效、易用的PDF编…...
JDBC知识
JDBC是什么? 这工作中我们针对数据库的操作,实际上很少会用到SQL语句,通过命令行/图形化来操作数据库,更多的是通过主流的编程语言来对数据库进行操作,即使通过代码来操作数据,我们还是会使用到SQL语句,所以掌握SQL语句也是很重要的. 如何通过代码操作数据库? 通过代码操作…...
C++操纵符用法
C中的操纵符(Manipulators)是用于格式化输入输出的特殊工具。它们可以在输出流中控制各种格式,如设置字段宽度、精度、填充字符等。以下是一些常用的操纵符及其用法: setw(int width): 设置字段宽度为width个字符。 cout <<…...
【一步一步了解Java系列】:子类继承以及代码块的初始化
看到这句话的时候证明:此刻你我都在努力 加油陌生人 个人主页:Gu Gu Study专栏:一步一步了解Java 喜欢的一句话: 常常会回顾努力的自己,所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者:小闭 …...
探索Expect Python用法:深入解析与实战挑战
探索Expect Python用法:深入解析与实战挑战 在自动化和脚本编写领域,Expect Python已经成为了一种强大的工具组合。它结合了Expect的交互式会话处理能力和Python的编程灵活性,为开发者提供了一种全新的方式来处理复杂的自动化任务。然而&…...
【PostgreSQL17新特性之-explain命令新增选项】
EXPLAIN是一个用于显示语句执行计划的命令,可用于显示以下语句类型之一的执行计划: - SELECT - INSERT - UPDATE - DELETE - VALUES - EXECUTE - DECLARE - CREATE TABLE AS - CREATE MATERIALIZED VIEWPostgreSQL17-beta1版本近日发布了,新…...
JAVA实现人工智能,采用框架SpringAI
文章目录 JAVA实现人工智能,采用框架SpringAISpring AI介绍使用介绍项目前提项目结构第一种方式采用openai1. pom文件: 2. application.yml 配置3.controller 实现层 项目测试 JAVA实现人工智能,采用框架SpringAI Spring AI介绍 Spring AI是AI工程师的一个应用框架…...
基础—SQL—DQL(数据查询语言)分组查询
一、引言 分组查询的关键字是:GROUP BY。 二、DQL—分组查询 1、语法 SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后过滤条件 ]; 注意: 1、[ ] 里的内容可以有可以没有。 2、这条SQL语句有两块指定条件的地方&#…...
从CSV到数据库(简易)
需求:客户上传CSV文档,要求CSV文档内容查重/插入/更新相关数据。 框架:jdbcTemplate、commons-io、 DB:oracle 相关依赖: 这里本来打算用的2.11.0,无奈正式项目那边用老版本1.3.1,新版本对类型…...
别再踩坑了!Django Ckeditor配置全指南:从基础使用到高级定制(2023最新版)
Django Ckeditor实战手册:2023年高效配置与深度定制技巧 如果你正在为Django项目寻找一个功能强大且可定制的富文本编辑器,Ckeditor无疑是最佳选择之一。但配置过程中那些令人头疼的兼容性问题、图片上传失败、工具栏自定义困难,确实让不少开…...
抖音批量下载助手:轻松管理您的抖音视频资源库
抖音批量下载助手:轻松管理您的抖音视频资源库 【免费下载链接】douyinhelper 抖音批量下载助手 项目地址: https://gitcode.com/gh_mirrors/do/douyinhelper 还在为手动保存抖音视频而烦恼吗?抖音批量下载助手正是您需要的效率工具!这…...
TTL门电路在现代数字设计中的应用:从基础到OC门实战
TTL门电路在现代数字设计中的应用:从基础到OC门实战 在数字电路设计的工具箱里,TTL(晶体管-晶体管逻辑)门电路就像瑞士军刀一样经典而实用。尽管CMOS技术如今占据主流,但TTL在特定场景下依然展现出独特的优势。特别是在…...
颠覆中文字体困境:思源宋体CN 7字重开源方案深度解析
颠覆中文字体困境:思源宋体CN 7字重开源方案深度解析 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 价值主张:破解中文字体的"三重枷锁" 在数字设计…...
Zotero重复条目智能处理指南:从混乱到有序的文献管理解决方案
Zotero重复条目智能处理指南:从混乱到有序的文献管理解决方案 【免费下载链接】ZoteroDuplicatesMerger A zotero plugin to automatically merge duplicate items 项目地址: https://gitcode.com/gh_mirrors/zo/ZoteroDuplicatesMerger 学术研究中ÿ…...
教无人机操控3年,这款仿真软件让我彻底告别“真机实训焦虑”
作为无人机专业实操教师,深耕一线教学3年,最大的痛点莫过于“真机实训难”——相信同行们都有共鸣,无人机操控教学看似是“练手”,实则处处是坑,每一个难题都让人头疼不已,甚至一度让我陷入教学焦虑。整理了…...
Cassandra在大数据图像存储中的应用探索
Cassandra在大数据图像存储中的应用探索关键词:Cassandra、大数据、图像存储、分布式系统、数据管理摘要:本文旨在深入探索Cassandra在大数据图像存储领域的应用。我们将先介绍Cassandra的基本概念和特点,再详细分析它与大数据图像存储的适配…...
OFA视觉蕴含模型效果展示:抽象艺术作品与评论文本关联性
OFA视觉蕴含模型效果展示:抽象艺术作品与评论文本关联性 1. 引言:当抽象艺术遇见智能理解 想象一下这样的场景:你站在一幅抽象画前,画布上是狂放的笔触和难以名状的色彩组合。旁边有人评论说:"这幅画表达了宇宙…...
马西奎《电磁场与电磁波》学习记录-第 2 章学前准备-坐标系的深入 + 微分元(dl、dS、dV)
一、正交坐标系的一般概念1. 什么是正交曲线坐标系三组坐标面互相垂直正交单位矢量处处正交:⊥⊥直角、圆柱、球坐标都属于这一类。2. 坐标变量与拉梅系数(度量系数)对一般正交曲线坐标 (,,):坐标面:常数、…...
野火挑战者开发板实战:用STM32CubeMX从零配置GPIO、UART和ADC(附完整代码)
野火挑战者开发板实战:从零构建环境监测系统 刚拿到野火挑战者开发板时,面对密密麻麻的引脚和复杂的配置选项,很多初学者会感到无从下手。本文将带你用STM32CubeMX图形化工具,快速配置GPIO、UART和ADC这三个最常用的外设ÿ…...
