深入研究java对String字符串对象的创建以及管理

ANSYS 有限元分析 接触分析 目 录一、前沿二、接触单元类三、接触单元关键选项3.1 CONTA174 KeyOption3.2 TARGE170 KeyOption四、接触分析标准步骤4.1 定义实常数4.2 定义接触和目标单元4.3 创建接触和目标单元五、接触分析实例5.1 MPC5.2 标准接触六、尾声七、参考文献 阿阳的 ANSYS 使用指南,本文仅用于个人学习,除此之外,无其他任何用途。 ANSYS 有限元分析 概述 ANSYS 有限元分析 坐标系/工作平面 ANSYS 有限元分析 几何建模 ANSY 阅读详情

经常看到很多人讨论java中关于String的问题,我也就有点兴趣了,鉴于网上很多人写的都差别很大,
同样的问题都是不同的说法,我很迷糊,花了一晚上读了Java Virtual Machine Specification和
The Java Language Specification的一些章节,做了很多试验,总结了一下关于String的内容,还
有很多内容我也不确定,在下面也都提出来了,希望高手能指正.


Constant Pool常量池的概念:

在讲到String的一些特殊情况时,总会提到String Pool或者Constant Pool,但是我想很多人都不太
明白Constant Pool到底是个怎么样的东西,运行的时候存储在哪里,所以在这里先说一下Constant Pool的内容.
String Pool是对应于在Constant Pool中存储String常量的区域.习惯称为String Pool,也有人称为
String Constant Pool.好像没有正式的命名??

在java编译好的class文件中,有个区域称为Constant Pool,他是一个由数组组成的表,类型
为cp_info constant_pool[],用来存储程序中使用的各种常量,包括Class
/String/Integer等各
种基本Java数据类型,详情参见The Java Virtual Machine Specification
4.4章节.


对于Constant Pool,表的基本通用结构为:
cp_info {
        u1 tag;
        u1 info[];
}


tag是一个数字,用来表示存储的常量的类型,例如8表示String类型,5表示Long类型,info[]根据
类型码tag的不同会发生相应变化.

对于String类型,表的结构为:
CONSTANT_String_info {
        u1 tag;
        u2 string_index;
}

tag固定为8,string_index是字符串内容信息,类型为:
CONSTANT_Utf8_info {
        u1 tag;
        u2 length;
        u1 bytes[length];
}

tag固定为1,length为字符串的长度,bytes[length]为字符串的内容.

(以下代码在jdk6中编译)
为了详细理解Constant Pool的结构,我们参看一些代码:
    String s1
= "sss111";
    String s2
= "sss222";
    System.out.println(s1
+ " " + s2);

由于
"sss111"和"sss222"都是字符串常量,在编译期就已经创建好了存储在class文件中.
在编译后的class文件中会存在这2个常量的对应表示:
08 00 11 01 00 06 73 73 73 31 31 31 08 00 13 01 ; ......sss111....
00 06 73 73 73 32 32 32                         ; ..sss222

根据上面说的String常量结构,我们分析一下
开始的08为CONSTANT_String_info结构中的tag,而11应该是它的相对引用,01为
CONSTANT_Utf8_info的tag,06为对应字符串的长度,
73 73 73 31 31 31为字符串对
应的编码,接着分析,会发现后面的是对应
"sss222"的存储结构.


经过上面分析,我们知道了11和13是两个字符串的相对引用,就可以修改class文件
来修改打印的内容,把class文件中的
00 6E 00 04 00 03 00 00 00 24 12 10 4C 12 12 4D
改成
00 6E 00 04 00 03 00 00 00 24 12 10 4C 12 10 4D
程序就会输出sss111 sss111,而不是和原程序一样输出sss111 sss222,因为我
们把对
"sss222"的相对引用12改成了对"sss111"的相对引用10.


------------分割线
public class Test {
   
public static void main(String[] args) {
        String s1
= "sss111";
        String s2
= "sss111";
    }
}

在上面程序中存在2个相同的常量
"sss111",对于n个值相同的String常量,在Constant Pool中
只会创建一个,所以在编译好的class文件中,我们只能找到一个对
"sss111"的表示:
000000abh:
08 00 11 01 00 06 73 73 73 31 31 31             ; ......sss111


在程序执行的时候,Constant Pool会储存在Method Area,而不是heap中.

另外,对于
""内容为空的字符串常量,会创建一个长度为0,内容为空的字符串放到Constant Pool中,
而且Constant Pool在运行期是可以动态扩展的.


关于String类的说明
1.String使用private final char value[]来实现字符串的存储,也就是说String对象创建之后,就不能
再修改此对象中存储的字符串内容,就是因为如此,才说String类型是不可变的(immutable).

2.String类有一个特殊的创建方法,就是使用""双引号来创建.例如new String("i am")实际创建了2个
String对象,一个是
"i am"通过""双引号创建的,另一个是通过new创建的.只不过他们创建的时期不同,
一个是编译期,一个是运行期
!

3.java对String类型重载了+操作符,可以直接使用+对两个字符串进行连接.

4.运行期调用String类的intern()方法可以向String Pool中动态添加对象.

String的创建方法一般有如下几种
1.直接使用""引号创建.
2.使用new String()创建.
3.使用new String("someString")创建以及其他的一些重载构造函数创建.
4.使用重载的字符串连接操作符+创建.

例1
   
/*
    * "sss111"是编译期常量,编译时已经能确定它的值,在编译
    * 好的class文件中它已经在String Pool中了,此语句会在
    * String Pool中查找等于"sss111"的字符串(用equals(Object)方法确定),
    * 如果存在就把引用返回,付值给s1.不存在就会创建一个"sss111"放在
    * String Pool中,然后把引用返回,付值给s1.
    *
   
*/
    String s1
= "sss111";

   
//此语句同上
    String s2 = "sss111";

   
/*
    * 由于String Pool只会维护一个值相同的String对象
    * 上面2句得到的引用是String Pool中同一个对象,所以
    * 他们引用相等
   
*/
    System.out.println(s1
== s2); //结果为true


例2
   
/*
    * 在java中,使用new关键字会创建一个新对象,在本例中,不管在
    * String Pool中是否已经有值相同的对象,都会创建了一个新的
    * String对象存储在heap中,然后把引用返回赋给s1.
    * 本例中使用了String的public String(String original)构造函数.
   
*/
    String s1
= new String("sss111");
   
   
/*
     * 此句会按照例1中所述在String Pool中查找
    
*/
    String s2
= "sss111";
   
   
/*
     * 由于s1是new出的新对象,存储在heap中,s2指向的对象
     * 存储在String Pool中,他们肯定不是同一个对象,只是
     * 存储的字符串值相同,所以返回false.
    
*/
    System.out.println(s1
== s2); //结果为false


例3
    String s1
= new String("sss111");
   
/*
    * 当调用intern方法时,如果String Pool中已经包含一个等于此String对象
    * 的字符串(用 equals(Object)方法确定),则返回池中的字符串.否则,将此
    * String对象添加到池中,并返回此String对象在String Pool中的引用.
   
*/
    s1
= s1.intern();
   
    String s2
= "sss111";
   
   
/*
     * 由于执行了s1 = s1.intern(),会使s1指向String Pool中值为"sss111"
     * 的字符串对象,s2也指向了同样的对象,所以结果为true
    
*/
    System.out.println(s1
== s2);


例4
    String s1
= new String("111");
    String s2
= "sss111";
   
   
/*
    * 由于进行连接的2个字符串都是常量,编译期就能确定连接后的值了,
    * 编译器会进行优化直接把他们表示成"sss111"存储到String Pool中,
    * 由于上边的s2="sss111"已经在String Pool中加入了"sss111",
    * 此句会把s3指向和s2相同的对象,所以他们引用相同.此时仍然会创建出
    * "sss"和"111"两个常量,存储到String Pool中.

   
*/
    String s3
= "sss" + "111";
   
   
/*
     * 由于s1是个变量,在编译期不能确定它的值是多少,所以
     * 会在执行的时候创建一个新的String对象存储到heap中,
     * 然后赋值给s4.
    
*/
    String s4
= "sss" + s1;
   
    System.out.println(s2
== s3); //true
    System.out.println(s2 == s4); //false
    System.out.println(s2 == s4.intern()); //true


例5
这个是The Java Language Specification中3.
10.5节的例子,有了上面的说明,这个应该不难理解了
   
package testPackage;
   
class Test {
           
public static void main(String[] args) {
                    String hello
= "Hello", lo = "lo";
                    System.out.print((hello
== "Hello") + " ");
                    System.out.print((Other.hello
== hello) + " ");
                    System.out.print((other.Other.hello
== hello) + " ");
                    System.out.print((hello
== ("Hel"+"lo")) + " ");
                    System.out.print((hello
== ("Hel"+lo)) + " ");
                    System.out.println(hello
== ("Hel"+lo).intern());
            }
    }
   
class Other { static String hello = "Hello"; }

   
package other;
   
public class Other { static String hello = "Hello"; }

输出结果为true
true true true false true,请自行分析!


结果上面分析,总结如下:
1.单独使用""引号创建的字符串都是常量,编译期就已经确定存储到String Pool中.
2.使用new String("")创建的对象会存储到heap中,是运行期新创建的.
3.使用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能确定,已经确定存储到String Pool中.
4.使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中.
6.使用"aa" + s1以及new String("aa" + s1)形式创建的对象是否加入到String Pool中我不太确定,可能是必须
调用intern()方法才会加入,希望高手能回答 @_@


还有几个经常考的面试题:

1.
String s1
= new String("s1") ;
String s2
= new String("s1") ;
上面创建了几个String对象
?
答案:3个 ,编译期Constant Pool中创建1个,运行期heap中创建2个.


2.
String s1
= "s1";
String s2
= s1;
s2
= "s2";
s1指向的对象中的字符串是什么
?
答案:
"s1"

手把手教你ensp仿真搭建校园网(含防火墙及无线网络)系列(三)校园无线网络AC+AP配置 本系列博客将带你从零开始,使用 华为 eNSP(Enterprise Network Simulation Platform) 仿真搭建一个完整的校园网络,涵盖 核心层、汇聚层、接入层、防火墙安全策略、无线AC+AP组网 等实战场景。无论你是网络初学者还是希望深化实战经验的工程师,都能通过本教程掌握企业级网络的规划、配置与排错技巧。 阅读详情

相关推荐

多模态情感识别(MER)数据集实战指南:从IEMOCAP到应用落地

本文提供了多模态情感识别(MER)从数据集到应用落地的完整实战指南。以经典IEMOCAP数据集为例,详细讲解了音频、视觉、文本等多模态数据的预处理、特征提取与融合技术,并分享了模型训练调优心得及面向智能客服、在线教育等场景的部署考量,帮助开发者快速构建高效可用的MER系统。

h3i4j的博客 1071

Java基础-String对象的创建和存储

虽然堆中的对象都指向的是“xyz”中的字符串常量池中的内存地址,但栈中的x和y都指向x和y在堆内存中的不同的堆内存地址。如果堆里面new的是一个User对象,User对象里有一个String类型的name属性,则User的name里存储的并不是具体的字符串,而是存储的是字符串在字符串常量池中的内存地址。方式二的内存图,s3在内存中存在的形式就是,栈中的s3的内存地址指向堆中的String对象,堆中的String对象中的内存地址又指向方法区中“xy”的内存地址。且“==”判断的是内存地址。

flytalei的博客 3966

ros1 Noetic下运行cartographer算法进行2d建图

最近的工作重点放在机器狗的二次开发上,项目的需求是要升级机器狗的slam算法和导航避障算法,slam拟采用激光与视觉融合算法,激光slam就使用最为流行和实用的cartoghper算法。在这过程中遇到好多坑,希望看到这篇博客的人能少走弯路吧。我用的仿真机器人是wpr_simiulation。首先复制一份demo_revo_lds.launch文件和revo_lds.lua文件,修改成下面的样子。my_test.lua文件,base_link就是机器人的坐标系。下载与安装的博客有很多,我推荐。

sun5739的博客 1549

Java创建字符串对象详解

JAVA创建对象有两种方式,一种是通过字符串常量的方式创建,比如String str=“abc”,一种是字符串变量通过new形式的创建,比如String str = new String(“abc”) String str = "abc"创建过程 首先在常量池中查找是否存在内容为"abc"字符串对象 如果不存在则在常量池中创建"abc",并让str引用该对象(也就是创建1个对象的情况) 如果存在则直接让str引用该对象(该对象是存在方法区的运行时常量池中的)(也就是创建0个对象的情况) Java中

weixin_45659364的博客 2900

YOLO11改进-注意力-引入Deformable Large Kernel Attention (DLKA) 解决多尺度、小目标、遮挡等问题

Deformable Large Kernel Attention (DLKA) 是一种用于视觉任务的注意力机制,旨在提升模型在处理不同尺寸和形状对象时的灵活性和性能。DLKA 的设计灵感源自传统的注意力机制,但通过引入可变形核(deformable kernel)来增强对局部特征的适应能力。

qq_64693987的博客 4042

30天入门Python(办公篇)——第34天:pandas - 数据处理与分析利器

摘要 本文介绍了Python数据分析库pandas的核心功能,包括数据结构和基本操作。主要内容涵盖:1) Series和DataFrame两种核心数据结构的创建与使用;2) 多种文件格式的读写方法;3) 数据查看、筛选和清洗技巧;4) 基础统计分析功能;5) 数据透视表和交叉表制作;6) 数据排序与合并等变换操作。文章通过大量代码示例演示了pandas在数据处理各环节的应用,适合作为pandas入门的实践指南,帮助读者快速掌握这一强大工具的基本使用方法。

weixin_42636075的博客 305

下面这条语句一共创建了多少个对象:String s=“a“+“b“+“c“+“d“;

作者:老紫竹 最近看到许多类似的帖子,大致意思如下: 问题1: String s = “a” + “b” + “c” + “d” + “e”; 问此语句共创建了几个对象? 答:就创建了一个 解析:String s = “a” + “b” + “c” + “d” + “e”; 赋值符号右边的"a"、“b”、“c”、“d”、“e"都是常量 对于常量,编译时就直接存储它们的字面值而不是它们的引用 在编译时就直接将它...

Xxacker的博客 8694

YOLOv8_obb训练流程-原理解析[旋转目标检测理论篇]

本文主要介绍了YOLOv8旋转目标检测的流程,介绍了标签的解码、预测结果的解码,以及如何理解旋转角度等内容,还介绍旋转目标检测框的正样本选取及Loss计算。

ice 4732

谓词推入的优化案例

案例很简单,主要就是长…… Sql文本: select count(*) from VIEW_SB_UUUUUUUUUUUUUUUUU where 1 = 1 and (KKKKID in (SELECT orgno FROM PP_OOO WHERE PARENTORGNO = '110000078...

24号信仰 1万+

如何使用 Python 爬虫爬取滴滴打车信息:获取司机和乘客数据

滴滴打车作为中国最大的打车平台之一,提供了丰富的司机和乘客数据,包括司机的车辆信息、乘客的评价、行程数据等。公开的司机和车辆信息(如司机的名字、车辆类型、评价等)可以通过网页直接获取,而乘客的个人信息和具体行程数据通常会受到隐私保护。在滴滴打车的网页中,司机的信息可能以特定的 HTML 标签存在,例如包含司机名称、车辆类型、车辆等级等信息。我们需要分析网页的 HTML 结构,找到这些数据所在的标签。同时,对于涉及到隐私的用户数据(如乘客的行程信息、用户评价等),我们必须特别谨慎,避免侵犯他人的隐私。

2201_76125261的博客 1918

【生信分析】clusterProfiler: universal enrichment tool for functional and comparative study(1)

clusterProfiler: universal enrichment tool for functional and comparative studyClusterProfiler: 用于功能和比较研究的通用富集工具总览1. 引言1.1 术语1.1.1 基因集和通路1.1.2 基因同源(GO)1.1.3 京都基因与基因组百科全书(KEGG)1.1.4 其他基因集2. 功能富集分析方法2.1 过度表征分析(Over Representation Analysis)2.2 基因集富集分析(Gene Se

小哲的博客 1366

java基础--String字符串对象

注意 : 打印字符串类型的变量,是不会看到字符串对象空间地址值的,底层是有优化的,直接看到字符串对象中存储的内容,底层打印对象十六进制地址值的代码。

weixin_53263488的博客 514

指纹浏览器 WebGPU:新一代图形指纹的检测趋势与提前防御

指纹浏览器与风控系统对抗已升级至硬件层面。传统基于WebGL的API拦截和像素噪声技术,在WebGPU时代因架构变革而失效。WebGPU通过Compute Shader直接测量GPU物理算力,暴露了软件模拟的致命缺陷。防御需转向真实GPU硬件直通和虚拟化技术,如vGPU分割算力并伪装特征,以应对风控系统对硬件拓扑和浮点精度的检测。唯有基于物理算力的拟态,才能抵御新一代图形指纹的降维打击。

数据知道的博客 221

深入研究java对String字符串对象的创建以及管理【转帖】

 深入研究java对String字符串对象的创建以及管理(2008-9-27 bbh)新手初学,不对的地方大家多多指教~经常看到很多人讨论java中关于String的问题,我也就有点兴趣了,鉴于网上很多人写的都差别很大,同样的问题都是不同的说法,我很迷糊,花了一晚上读了Java Virtual Machine Specification和The Java Language Specificatio

幸旺 702

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: 一个关于截取字符串的面试题!
下一篇: JAVA命名规范
不善^
博客等级 码龄18年 635粉丝 235原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值