字符串常量池字符串常量的几种创建方式及其位置

news2024/11/17 3:38:52

从JDK7开始,字符串常量池被移到了堆区中,因此Java程序中的字符串常量对象要么在堆区的字符串常量池之中,要么在堆区的字符串常量池之外。为了做区分,下文将堆区的字符串常量池区域称为字符串常量池,将堆区字符串常量池之外的区域称为堆区。

一.使用字面量直接赋值

String str = "abc";

1.使用这种方式可以保证字符串常量池中一定有字符串对象"abc"。

2.执行步骤:

(1)通过值比较的方式判断字符串常量池中是否有字符串对象"abc":

(2)若有,则直接将该对象的引用返回给str;

(3)若没有,则先在字符串常量池中创建字符串对象"abc",再将其引用返回给str。

3.特征:

(1)字符串常量池一定会有声明的字面量的字符串对象。

(2)创建对象的个数:[0,1]:

        a.只有当字符串常量池没有"abc"对象,才会创建。即字符串常量池中的对象具有唯一性。

        b.全程与堆区无关。

(3)返回的是指向字符串常量池中的引用。

二.使用new String(字面量)

String str = new String("abc");

1.使用这种方式可以保证字符串常量池和堆区都会有字符串对象"abc"。

2.执行步骤:

(1)通过值比较的方式判断字符串常量池中是否有字符串对象"abc":

(2)若有,则继续执行;

(3)若没有,则会在字符串常量池中创建字符串对象"abc";

(4)在堆区中创建字符串对象"abc",并将其引用返回。

3.特征:

(1)字符串常量池和堆中都一定会有声明的字面量的字符串对象。

(2)创建对象的个数:[1,2]。

       a.只有当字符串常量池没有"abc"对象,才会创建。即字符串常量池中的对象具有唯一性。

        b.一定会在堆区创建一个"abc"对象。因此堆区可能会有多个"abc"对象,每执行一次new String("abc")就会创建一个"abc"对象。

(4)返回的是指向堆中的引用。

三.使用new String(变量)

String str = new String(str1);

1.这种方式只会在堆中创建字符串对象。

2.解析:

(1)字符串常量池的来源链是:字节码文件的静态常量池——>静态常量池中的所有字符串常量——>堆中的字符串常量池。

(2)即字符串常量池中的数据都是在编译阶段确定的。像上述这种创建字符串对象的方式,由于涉及到变量,因此需要在在运行时动态构建,无法加入字符串常量池。

(3)str指向堆中的对象。

四.使用StringBuilder

String str = new StringBuilder().append("a").append("b").toString();

1.对于作为方法参数传递的字面量"a"、"b",因为其已经显示声明,在编译阶段是可知的,因此字符串常量池中会加入对象"a"、"b"。

(1)上述对显示声明的字面量字符串对象作为参数传递,可以拆解成以下步骤

String stra = "a";
String strb = "b";
String str = new StringBuilder().append(stra).append(strb).toString();

也就是说字符串对象"a"和"b"会被加入到字符串常量池中,但不会在堆中创建对象。

(2)由此可知,使用字面量作为参数传递时,该字面量也会被作为字符串对象加入到字符串常量池中。

2.上述语句的执行结果是str = "ab";但同样地,由于涉及到类的调用和方法的执行,因此对字符串对象"ab"是在运行时动态构建的,其只能在堆中创建对象,无法加入到字符串常量池中。

3.str指向堆中的对象。

4.验证:使用jclasslib查看编译成的字节码文件中的静态常量池

 

 可以看到,该类的静态常量池中唯二的两个字符串常量就是"a"和"b",它们会被作为字符串常量对象加入到字符串常量池中,而没有"ab"。

五.使用"+"连接

1.等号右边全为字面量

String str = "a" + "b";

(1)在编译阶段,编译器会对全由字面量构成的连接时进行优化,称为常量折叠。优化结果为

String str = "ab";

(2)字符串"a"和"b"由于常量折叠而丢失,不会创建任何对象。最终会为优化后得到的字符串"ab"在字符串常量池中创建对象。

(3)str指向字符串常量池中的对象

(4)验证:

可以看到,静态常量池中只有一个字符串常量"ab"。

2.等号右边至少含有一个变量

String str = str1 + "a" + "b";

 (1)只要涉及到对变量的操作,就只能在运行时动态构建。

(2)上述语句会在字符串常量池中创建字符串对象"a"和"b",会在堆中创建字符串对象作为动态执行的结果。

(3)str指向堆中的对象。

六.总结

1.对于代码中所有的字面量字符串,无论是显式声明用于构建String对象还是用于传参,只要不被常量折叠,就一定会为其在字符串常量池中创建对象。

2.对于通过调用类、变量、方法等方式动态构建的字符串,由于需要运行时动态构建,因此无法加入字符串常量池,只能在堆中创建对象。

七.String类提供的intern()方法

intern()方法会将字符串常量对象放到字符串常量池中,并返回其引用。对于不同的JDK版本有不同的实现:

///str是一个在堆中的字符串对象
System.out.println(str.intern() == str);

1.JDK6及之前的intern()方法:

(1)如果str在字符串常量池中,则返回其位于字符串常量池中的引用。输出结果为false。

(2)如果str不在字符串常量池中,则在字符串常量池中创建一个str并返回其引用。输出结果为false。

(3)str是对堆中的引用,而str.intern()只会返回字符串常量池中的引用,因此结果一定是false。

2.JDK7及之后的方法:

(1)如果str在字符串常量池中,则返回其位于字符串常量池中的引用。输出结果为false。

(2)如果str不在字符串常量池中,则在字符串常量池中存入对堆中str的引用,并将该引用返回,而不会再创建一个对象。输出结果为true。

(3)str是对堆中的引用,而str.intern()的返回结果有两种可能:对字符串常量池中的引用、对字符串常量池的引用——>对堆中对象的引用。

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

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

相关文章

汇编语言作业(六)

目录 一、实验目的 二、实验内容 三、实验步骤以及结果 四、实验结果与分析 五、实验总结 一、实验目的 掌握加减法运算指令对各状态标志位的影响及测试方法掌握汇编语言长整数的加法的操作方法 二、实验内容 对于以下几组数, 087H和034H 0C2H和5FH 0F3H和0F3H&am…

6.7 作业

搭建一个货币的场景,创建一个名为 RMB 的类,该类具有整型私有成员变量 yuan(元)、jiao(角)和 fen(分),并且具有以下功能: (1)重载算术运算符 和 -&#xff…

kettle从入门到精通 第六十七课 ETL之kettle 再谈kettle阻塞,阻塞多个分支的多个步骤

想真正学习或者提升自己的ETL领域知识的朋友欢迎进群,一起学习,共同进步。由于群内人员较多无法直接扫描进入,公众号后台加我微信入群,备注kettle。 场景:ETL沟通交流群内有小伙伴反馈,如何多个分支处理完…

C# 解决 Excel 自动适应列宽的问题

目录 问题现象 原因分析 范例运行环境 解决问题 生成测试文本 实现自适应 小结 问题现象 通过 COM 操作 Excel 自动适应列宽的方法是 AutoFit 方法,该方法适于自动适应列宽或行高。 最近在我们的一款应用里发现效果并没有符合预期,我们提供了一…

vAttention:用于在没有Paged Attention的情况下Serving LLM

文章目录 0x0. 前言(太长不看版)0x1. 摘要0x2. 介绍&背景0x3. 使用PagedAttention模型的问题0x3.1 需要重写注意力kernel0x3.2 在服务框架中增加冗余0x3.3 性能开销0x3.3.1 GPU上的运行时开销0x3.3.2 CPU上的运行时开销 0x4. 对LLM服务系统的洞察0x5…

VUE2.7项目配置webpack打包-详细操作步骤

一、Webpack简介 Webpack是一个打包工具,可以把JS、CSS、Node Module、Coffeescrip、SCSS/LESS、图片等都打包在一起,因此,现在几乎所有的SPA项目、JS项目都会用到Webpack。 官网:https://webpack.js.org GitHub为https://git…

全球溃败,苹果可能要全球大降价了,试图摆脱中国制造的后果

苹果一季度在中国市场的出货量暴跌,导致它不得不在中国市场大降价,从3月份就在中国市场大幅度降价,然而目前它在美国和欧洲两大市场也出现大幅衰退,降价可能将成为苹果在全球的举措。 市调机构Canalys公布的一季度数据显示&#x…

MySQL高性能(SQL性能分析)

MySQL性能系列 SQL性能分析 前言1.SQL执行评率2. 慢查询日志3. profile详情4. Explain执行计划4.1. Explain — id4.2. Explain — type4.3. Explain — table4.4. Explain — key 前言 本篇文章采用的MySQL版本是8代,同时自己使用的是Linux mysql8,本篇…

SOA的设计模式_3.微服务模式

SOA的架构中,复杂的ESB企业服务总线依然处于非常重要的位置,整个系统的架构并没有实现完全的组件化以及面向服务,它的学习和使用门槛依然偏高。而微服务不再强调传统SOA架构里面比较重的ESB企业服务总线,同时SOA的思想进入到单个业…

多态的应用——数组多态

介绍 ai查询 在Java中,动态数组通常通过ArrayList类来实现,它是Java集合框架(Java Collections Framework)的一部分。ArrayList是一个可调整大小的数组实现,提供了比标准数组更多的灵活性和功能。 以下是使用ArrayLis…

安装后或升级启智环境到飞桨2.6版本(develop)

启智社区的启智大脑调试环境非常好用,但是里面的飞桨环境版本比较低,为了能够运行大模型(llm),需要升级飞桨到2.6版本或者开发版本。 首先创建启智大脑调试环境,注意选cuda12.1的环境。 进入调试环境后&am…

Discuz! X3.4免备案无执照接入支付宝微信支付插件

下载地址:Discuz! X3.4免备案无执照接入支付宝微信支付插件 [充值会员]支付宝当面付版 微信支付

MySQL普通表转换为分区表实战指南

码到三十五 : 个人主页 引言 本文将详细指导新手开发者如何将MySQL中的普通表转换为分区表。分区表在处理庞大数据集时展现出显著的性能优势,不仅能大幅提升查询速度,还能有效简化数据维护工作。通过掌握这一技巧能够更好地应对数据密集型应…

简单聊一下Oracle,MySQL,postgresql三种锁表的机制,行锁和表锁

MySQL: MySQL使用行级锁定和表级锁定。行级锁定允许多个会话同时写入表,适用于多用户、高并发和OLTP应用。表级锁定只允许一个会话一次更新表,适用于只读、主要读取或单用户应用。 比如mysql开启一个窗口执行 begin; update xc_county_a…

【C++初阶学习】第十三弹——优先级队列及容器适配器

C语言栈:数据结构——栈(C语言版)-CSDN博客 C语言队列:数据结构——队列(C语言版)-CSDN博客 C栈与队列:【C初阶学习】第十二弹——stack和queue的介绍和使用-CSDN博客 前言: 在前面,我们已经…

SpringMVC[从零开始]

SpringMVC SpringMVC简介 1.1什么是MVC MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分 M:Model,模型层,指工程中的JavaBean,作用是处理数据 JavaBean分为两类: 一类称为实体类Bean:专…

利用阿里云PAI平台微调ChatGLM3-6B

1.介绍ChatGLM3-6B ChatGLM3-6B大模型是智谱AI和清华大学 KEG 实验室联合发布的对话预训练模型。 1.1 模型规模 模型规模通常用参数数量(parameters)来衡量。参数数量越多,模型理论上越强大,但也更耗费资源。以下是一些典型模型…

1688商品库存查询

目录 下载安装与运行 功能简介 快速入门(视频) 当前支持的导出项 常用功能 历史商品是什么意思 粘贴商品有什么要求 导入商品需要什么样的模板 单个商品的查看 查看单个商品详情 下载安装与运行 下载、安装与运行 语雀 功能简介 最近一次测…

InternLM Xtuner Qlora 微调

Xtuner 简介 XTuner 是由上海人工智能实验室开发的一款低成本大模型训练工具箱。它以高效、灵活和全能的特性,成为轻量化大模型微调的理想选择。借助 XTuner,用户仅需 8GB 显存即可对 InternLM2-7B 模型进行微调,从而定制出独一无二的 AI 助手…

【OC】类与对象

类与对象 定义类接口部分定义成员变量方法说明实现部分 对象的产生与使用对象与指针self关键字避免重复创建 id类型方法详解方法的所属性形参个数可变的方法 成员变量成员变量及其运行机制多个实例中内存示意图模拟类变量单例模式 类是面向对象的重要内容,我们可以把…