数据结构-----再谈String,字符串常量池,String对象的创建、intern方法的作用

文章目录

  • 1.字符串常量池
    • 1.1. 创建对象的思考
    • 2.2. 字符串常量池(StringTable)
    • 1.3. 再谈String对象创建
    • 1.4. intern方法

1.字符串常量池

1.1. 创建对象的思考

下面两种创建String对象的方式相同吗?

public static void main(String[] args) {String s1 = "hello";String s2 = "hello";String s3 = new String("hello");String s4 = new String("hello");System.out.println(s1 == s2);    // trueSystem.out.println(s1 == s3);    // falseSystem.out.println(s3 == s4);    // false
}

上述程序创建方式类似,为什么s1和s2引用的是同一个对象,而s3和s4不是呢?

  • 在Java中,字符串常量池是一种特殊的运行时常量池,用于存储String类的字符串字面常量。字符串常量池的主要目的是避免重复创建相同的字符串对象,从而节省内存和提高运行效率。

  • 当在Java程序中使用字符串字面常量(如"hello")时,如果字符串常量池中已经存在相同内容的字符串对象,则不会创建新的对象,而是直接引用已存在的对象。这样做可以减少内存消耗,特别是在字符串频繁创建和使用的情况下。

在Java程序中,类似于:1, 2, 3,3.14,“hello”等字面类型的常量经常频繁使用,为了使程序的运行速度更快、更节省内存,Java为8种基本数据类型和String类都提供了常量池。

“池” 是编程中的一种常见的, 重要的提升效率的方式, 我们会在未来的学习中遇到各种 “内存池”, “线程池”, “数据库连接池” …
比如:家里给大家打生活费的方式

  1. 家里经济拮据,每月定时打生活费,有时可能会晚,最差情况下可能需要向家里张口要,速度慢
  2. 家里有矿,一次性打一年的生活费放到银行卡中,自己随用随取,速度非常快

方式2,就是池化技术的一种示例,钱放在卡上,随用随取,效率非常高。常见的池化技术比如:数据库连接池、线程池等。

为了节省存储空间以及程序的运行效率,Java中引入了:

  1. Class文件常量池:每个.Java源文件编译后生成.Class文件中会保存当前类中的字面常量以及符号信息
  2. 运行时常量池:在.Class文件被加载时,.Class文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都有一份
  3. 字符串常量池:字符串常量池是运行时常量池中的一部分。在Java中,字符串是不可变的对象,为了节省内存并提高性能,字符串常量池被引入。当你创建一个字符串常量时(例如使用双引号括起来的字符串字面值),Java会首先检查字符串常量池中是否已经有相同值的字符串对象。如果有,则返回常量池中的对象引用,而不是创建一个新的字符串对象。这样可以避免创建重复的字符串对象,从而节省内存空间。

使用字符串常量池的优势在于:

  1. 节省内存:避免了创建大量相同内容的字符串对象,降低了内存占用。

  2. 提高效率:由于字符串常量池中的对象是可复用的,当需要创建相同内容的字符串时,可以直接引用常量池中的对象,避免了对象的重复创建和销毁过程,从而提高了程序的执行效率。

注意:虽然字符串常量池在一定程度上提高了程序的性能,但过度的使用字符串常量可能会导致一些问题。例如,如果在程序中大量使用字符串常量拼接,每次拼接都会生成一个新的String对象,这种情况下使用StringBuilder或StringBuffer等可变字符串类更合适,因为它们可以避免创建过多临时的String对象。

2.2. 字符串常量池(StringTable)

字符串常量池在JVM中是StringTable类,实际是一个固定大小的HashTable(一种高效用来进行查找的数据结构),不同JDK版本下字符串常量池的位置以及默认大小是不同的:

JDK版本字符串常量池位置大小设置
Java6(方法区)永久代固定大小:1009
Java7堆中可设置,没有大小限制,默认大小:60013
Java8堆中可设置,有范围限制,最小是1009

在这里插入图片描述

1.3. 再谈String对象创建

由于不同JDK版本对字符串常量池的处理方式不同,此处在Java8 HotSpot上分析

  1. 直接使用字符串常量进行赋值
public static void main(String[] args) {String s1 = "hello";String s2 = "hello";System.out.println(s1 == s2);    // true
}

在上述代码中有两个字符串字面常量 “hello”,那么它们都会被放入字符串常量池,并且只有一个实际的String对象用于表示这个内容。这样,当程序中其他部分使用了相同的字符串字面常量 “hello”,都会共享这个已存在的String对象。
在这里插入图片描述

在这里插入图片描述
存储字符串常量的时候,会先检查当前常量池是否存在你所要存储的常量。
在这里插入图片描述

  1. 通过new创建String类对象
public static void main(String[] args) {String s1 = "hello";String s2 = "hello";String s3 = new String("hello");String s4 = new String("hello");System.out.println(s1 == s2);    // trueSystem.out.println(s1 == s3);    // falseSystem.out.println(s3 == s4);    // false
}

常量池存在“hello”,此时不在常量中存储hello,此时只需要重新创建一个String对象那个,将它的value域存放hello数组的地址,指向那个hello数组
在这里插入图片描述

public static void main(String[] args) {String s1 = "hello";String s2 = "hello";String s3 = new String("world");String s4 = new String("world");
}

在这里插入图片描述
常量池不存在“world”,此时需要在常量中存储world。
在这里插入图片描述

结论:只要是new的对象,都是唯一的。

通过上面例子可以看出,使用常量串创建String类型对象的效率更高,而且更节省空间,用户也可以将创建的字符串对象通过intern方式添加进字符串常量池中。

1.4. intern方法

intern 是一个native方法(Native方法指:底层使用C++实现的,看不到其实现的源代码),该方法的作用是手动将创建的String对象添加到常量池中。

public static void main(String[] args) {char[] ch = new char[]{'a', 'b', 'c'};String s1 = new String(ch);     // s1对象并不在常量池中//s1.intern();                 // s1.intern();调用之后,会将s1对象的引用放入到常量池中String s2 = "abc";        // "abc" 在常量池中存在了,s2创建时直接用常量池中"abc"的引用System.out.println(s1 == s2);// 输出false
}// 将上述方法打开之后,就会输出true

在这里插入图片描述

当代码运行到String s1 = new String(ch);时,我们发现在常量池中没有任何的数据,继续运行
在这里插入图片描述

public static void main(String[] args) {char[] ch = new char[]{'a', 'b', 'c'};String s1 = new String(ch);     // s1对象并不在常量池中s1.intern();                 // s1.intern();调用之后,会将s1对象的引用放入到常量池中String s2 = "abc";        // "abc" 在常量池中存在了,s2创建时直接用常量池中"abc"的引用System.out.println(s1 == s2);// 将方法打开之后,就会输出true
}

在这里插入图片描述
需要注意的是,虽然 intern() 方法可以减少重复字符串对象的内存占用,但滥用它也可能导致常量池过度膨胀,增加内存开销。在某些情况下,过度使用 intern() 方法可能会影响性能,因此在使用时需要谨慎考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/710468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我用 Navicat 的这些技能少加了好多班,也为公司挣了不少w

今天又用 Navicat 解决了一个数据同步的需求,财务又到账一笔收入....... 本文我将结合我过去的实践,给大家推荐一款数据库的运维工具。给大家呈现一下竟然可以用 Navicat 解决这些实际问题 。 熬了几个夜,毫无保留地将这些技能分享&#xf…

vue中动态引入图片

分析 很多时间,不管是vue2,还是vue3开发中都会遇到,动态渲染图片的功能,但是为什么我们直接将图片的路径直接赋值给变量的时候,图片渲染不出来,而通过require引入加载图片后却能正常渲染呢?主要…

华为HarmnyOS TypeScript基础语法快速入门

华为HarmnyOS TypeScript基础语法快速入门 一、JavaScript、TypeScript、ArkTS二、TypeScript基础语法1. 基础类型2. 条件语句3. 函数4. 类5. 模块6. 迭代器 一、JavaScript、TypeScript、ArkTS ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript(简称TS&am…

Axios入门

1.概念 Axios是一个开源的可以用在浏览器和node.js的异步通信框架,他的主要功能是实现Ajax异步通信 2.Axios入门程序 2.1.准备json格式的文件 {"name": "小明","address": {"street": "雁塔","city"…

动画原理:表面形变算法的思考与总结

前言: 之前我的文章 Mesh形变算法_mesh算法-CSDN博客就有大致的讨论过,介绍的也比较粗略!现在主要是想在Triangulated Surface Mesh Deformation方向上更深入的讨论一下!结合今年我对这一块的学习谈谈我的理解~ 下面要介绍大致几…

MySQL(基础篇)——函数、约束

一.函数 1.定义 函数是指一段可以直接被另一段程序调用的程序或代码。 2.字符串函数 常见如下: -- 字符串拼接 SELECT CONCAT(hello,MySql) AS CONCAT -- 将字符串全部转为小写 SELECT LOWER(HEllo MYSql) AS LOWER -- 将字符串全部转为大写 SELECT UPPER(Hello…

环境配置 |Jupyter lab/Jupyter Notebook 安装与设置

ipynb使用Jupyterlab/Jupyter Notebook 来编写Python程序时的文件,在使用时,可以现转换为标准的.py的python文件 1.Jupyter Lab 1.1.下载安装 环境:Linux pip install jupyterlab 1.2.使用 jupyter lab 点击后进入 1.3.jupyter lab更换内核 因为我的是在anac…

178文章复现:基于matlab的微震图像去噪

文章复现:基于matlab的微震图像去噪,利用同步压缩连续小波变换进行自动微震去噪和起始检测,SS-CWT 可对时间和频率变化的噪声进行自适应过滤,可以去除小幅值信号中的大部分噪声,检测地震事件并估算地震发生时间。程序已…

数据结构之树结构(上)

存储方式 数组存储方式的分析 优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。 缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效…

小(2)型土石坝安全监测设施配置详解

小(2)型土石坝的安全监测是确保大坝稳定、安全运行的重要环节。为此,合理配置安全监测设施显得尤为重要。以下是对小(2)型土石坝安全监测设施配置的详细介绍。 一、渗流量监测 渗流量是反映大坝安全状况的关键指标之一。为准确监测渗流量,我们采用仪器量…

day05_用户管理minIO角色分配(页面制作,查询用户,添加用户,修改用户,删除用户,用户头像,查询所有角色,保存角色数据)

文章目录 1 用户管理1.1 页面制作1.2 查询用户1.2.1 需求说明1.2.2 后端接口需求分析SysUserSysUserDtoSysUserControllerSysUserServiceSysUserMapperSysUserMapper.xml 1.2.3 前端对接实现思路sysUser.jssysRole.vue 1.3 添加用户1.3.1 需求说明1.3.2 页面制作1.3.3 后端接口…

ChatGPT-4 AI 绘图魔力释放

最近刚开通了 ChatGPT4,正好要设计一个网站图标,想测试一下它AI绘图的能力,让它根据文字描述生成一个想象中的图标 (PS:如果想体验 GPT4 文生图,可以看这个教程 如何升级 ChatGPT 4.0) 第1次交…

【三维重建】【SLAM】SplaTAM:基于3D高斯的密集RGB-D SLAM

题目:SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM 地址:spla-tam.github.io 机构:CMU(卡内基梅隆大学)、MIT(美国麻省理工) 总结:SplaTAM,一个新…

ywtool network命令

一.network功能介绍 network功能就是通过脚本的方式配置IP信息,分为4项: (1) 配置单网卡(2)配置br网桥(单网卡)(3)配置bond(两张网卡)(4)配置ovs网桥(单网卡) 日志文件:/var/log/ywtools/ywtools-network.log/usr/local/ywtools/config/config.ini中network参数:…

从预训练到通用智能(AGI)的观察和思考

1.预训练词向量 预训练词向量(Pre-trained Word Embeddings)是指通过无监督学习方法预先训练好的词与向量之间的映射关系。这些向量通常具有高维稠密特征,能够捕捉词语间的语义和语法相似性。最著名的预训练词向量包括Google的Word2Vec&#…

项目实现json字段

有些很复杂的信息,我们一般会用扩展字段传一个json串,字段一般用text类型存在数据库。mysql5.7以后支持json类型的字段,还可以进行sql查询与修改json内的某个字段的能力。 1.json字段定义 ip_info json DEFAULT NULL COMMENT ip信息, 2.按…

应用存储与持久化数据卷

1、PV 引入场景: ① Deployment 管理的 pod,在做镜像升级的过程中,会产生新的 pod并且删除旧的 pod ,新旧 pod 之间如何复用数据? ② 宿主机宕机的时候,如何实现带卷迁移? ③ 多个 pod 之间&…

Redis 之三:发布订阅(pub/sub)

概念介绍 Redis 发布订阅 (pub/sub) 是一种消息通信模式,它允许客户端之间进行异步的消息传递 Redis 客户端可以订阅任意数量的频道。 模型中的角色 在该模型中,有三种角色: 发布者(Publisher):负责发送信…

[分类指标]准确率、精确率、召回率、F1值、ROC和AUC、MCC马修相关系数

准确率、精确率、召回率、F1值 定义: 1、准确率(Accuracy) 准确率是指分类正确的样本占总样本个数的比例。准确率是针对所有样本的统计量。它被定义为: 准确率能够清晰的判断我们模型的表现,但有一个严重的缺陷&…

在Windows系统中启动Redis服务

前言 Redis是一个开源、高性能的键值对数据库,常用于缓存、消息队列等场景。本文将详细指导您如何在Windows系统上启动Redis服务。 第一步:确认Redis安装 确保您已经在Windows系统上成功安装了Redis。官方提供了预编译好的Windows版本,您可…