Java字符串常量池及字符串判等解析
一、理解“==”的含义
“==”常用于两个对象的判等操作,在Java中,“==”主要有以下两种用法:
1、基础数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样;
2、引用数据类型:比较的是两个引用对象指向的内存地址是否相同。
二、字符串常量池
Java中字符串对象主要有两种创建方式,第一种是通过”字面量“赋值,例如:String str="HWY";第二种是通过new关键字创建新对象,
例如String str=new String("HWY");这两种创建String对象有什么区别呢?
要讨论这个问题,首先要明白JVM运行时数据区和字符串常量池(String Pool)
方法区:存储类信息、常量、静态变量,全局共享。
堆区:存放对象和数组,全局共享。
栈区:存放基本数据类型、对象的引用,线程私有。
创建字符串对象主要与方法区、堆区和栈区有关,最相关的是字符串池(String Pool),其位置在jdk1.7之后移动到堆中。
这样我们再回到之前的问题,通过”字面量“赋值,例如:String str="HWY"创建字符串对象时,会在字符串常量池中创建“HWY”的对象,并
存放一个它的引用。此时类并没有加载完成,main方法中还没有创建str,当main方法执行到String str="HWY"时,虚拟机会去字符串池中找是否
有equals(“HWY”)的String,然后把在字符串池中“HWY”的引用复制给str。
当通过new关键字创建新对象,例如String str=new String("HWY")时,无论字符串常量池中是否有equals(“HWY”)的String,都会在堆中开辟一
块新的内存地址,存放一个字符串对象“HWY”,并在常量池中存放该对象的引用(如果发现常量池中已经有了字符串常量“HWY”,就不会再去创建),此时str指向的是堆
中字符串对象的地址。
三、字符串判等解析
了解完两种不同方式创建字符串对象的区别之后,可以看一下以下几个例子:
例1:
输出结果为:
这是比较常见的字符串比较问题,输出结果为false。解析:String s1="HHH",会在字符串常量池中存放一个内容为“HHH”的String对象的引用,并将该引用赋值给s1,
new关键字在堆中创建了一个新的字符串对象,s2指向的该字符串对象在堆中的地址,s2与s1指向的是不同的地址,因而输出false。
例2:
输出结果为:
解析:对于直接做+运算的两个字符串(字面量)对象,并不会放入字符串常量池中,而是直接把运算后的结果放入字符串常量池中
(String s 1= "HE"+ "LLO", 会直接生成字面量为“HELLO"字符串对象 ,s1指向的字符串常量池中“HELLO”的引用, 此时s1==s5为true,
String s4=s2+s3;这句被Java编译器做了优化, 实际上使用StringBuilder调用append方法拼接字符串,再调用toString方法返回String对象实现的,
本质上也是在堆中开辟了新的内存空间,此时s4指向的是堆中新创建的字符串对象地址,因而s1==s4为false。
例3:
输出结果为:
解析:这里涉及到intern()方法的使用,当调用 intern 方法时,如果字符串常量池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),
则返回池中的字符串的引用。否则,将此 String 对象添加到池中,将堆中String对象的引用复制给字符串常量池中,并返回此 String 对象的引用(堆中)。
当s2调用intern()方法时,字符串常量池中已经存在“HWY”字符串,因而直接返回字符串常量池该字符串的引用,所以s2.intern()==s1为true;
对于String s3=new String("中南")+new String("大学");此时会在堆中创建3个对象“中南”、“大学”、“中南大学”,而在字符串常量池中只有“中南”、“大学”两个字符串的引用,
因为我没有明确new("中南大学"),所以在字符串常量池中并没有“中南大学”字符串的引用,此时s3调用intern()方法会将堆中“中南大学”字符串对象的地址复制到字符串
常量池中,然后返回堆中“中南大学”的地址,所以此时s4、s3、s3.intern()的引用地址都相同。
以上内容就是关于Java字符串常量池及字符串判等的总结。
Java字符串常量池及字符串判等解析的更多相关文章
- java——字符串常量池、字符串函数以及static关键字的使用、数组的一些操作函数、math函数
字符串常量池: 字符串比较函数: 字符串常用方法: 字符串截取函数: 字符串截取函数: static关键字使用: 要调用类中的static类型的变量的时候,可以用"类名.变量名&quo ...
- 【转】Error,java对常量池来说字符串xxx的UTF8表示过长的解决及其理解
做项目,客户端这里自己模拟json数据时,一时没忍住搞得json字符串太长了(idea上大概有600多行吧),这个问题就蹦出来了.老方法直接google.百度然后看到一堆有关String 字符串常量池 ...
- Java中的字符串常量池
ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...
- 转载:Java中的字符串常量池详细介绍
引用自:http://blog.csdn.net/langhong8/article/details/50938041 这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重 ...
- java字符串常量池——字符串==比较的一个误区
转自:https://blog.csdn.net/wxz980927155/article/details/81712342 起因 再一次js的json对象的比较中,发现相同内容的json对象使用 ...
- Java中的字符串常量池和JVM运行时数据区的相关概念
什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...
- Java中的字符串常量池,栈和堆的概念
问题:String str = new String(“abc”),“abc”在内存中是怎么分配的? 答案是:堆内存.(Tips:jdk1.8 已经将字符串常量池放在堆内存区) 题目考查的为Ja ...
- Java String:字符串常量池(转)
作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么? 字符串常量池的设计思想是什么? 字符串常量池在哪里? 如何操作字符串常量 ...
- String:字符串常量池
String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字 ...
随机推荐
- 使用AVPro Video在Unity中播放开场视频(CG)笔记
游戏中的开场CG(播放视频),采用的插件为AVPro Video1.x(和W的版本一致),Unity版本为2018.4.0f1 Asset Store:AVPro Video - Core Andro ...
- Java编程中经典语句收录
1.spring系列:约定优于配置(习惯大于配置): 2.Java:一次编译,处处运行 3.Unix:没有消息就是好消息
- Crash course statistics
Crash course statistics 01什么是统计学 描述性统计(Descriptive statistics) 推理统计可以得出之外的,基于"样本"的推论统计学来估计 ...
- Azure 实践(1)- Azure Devops Server 安装
1.Azure Devops介绍 Azure DevOps Server 2020 (之前的名称为TFS),作为微软Azure DevOps 的企业私有(on-premises)服务器,是一个为开发团 ...
- JStorm:概念与编程模型
1.集群架构 JStorm从设计的角度,就是一个典型的调度系统,简单集群的架构如下图所示,其中Nimbus可增加一个备节点,多个Supervisor节点组成任务执行集群. 1.1.Nimbus Nim ...
- Servelt&&JSP进阶
Servlet与JSP进阶 来自mkw的视频课程的总结 1.前言 内容包括 掌握Java Web核心特性,Servlet核心对象以及JSP九大内置对象.主要有以下的内容: 请求结构 && ...
- Ubuntu本地提权适配不同小版本内核(CVE-2017-16995)
朋友在执行的时候说有的会出现提权不成功,内核crash掉的现象.因为cred结构体的偏移量可能因为内核版本不同.内核编译选项不同而出现差异,作者给的exp偏移量是写死的,所以exp里面对应的偏移地址也 ...
- DFT、DTFT、DFS、FFT之间的关系
DFT.DTFT.DFS.FFT.FT.FS之间的关系 FT和FS是研究连续信号的,在数字信号处理中不涉及. 主要是前四种的关系: DFT(Discrete Fourier Transform):离散 ...
- SQL 练习26
查询 1990 年出生的学生名单 --方式1 SELECT * FROM Student WHERE Sage BETWEEN '1990-01-01' AND '1990-12-31' --方式2 ...
- NOIP 模拟 $12\; \text{简单的填数}$
题解 一个纯的贪心,被我搞成 \(dp\) 了,最后把错解删掉了,骗了 \(10pts\) 考虑如何贪心,设置一种二元组 \((x,l)\),\(x\) 表示当前值,\(l\) 表示当前最长连续长度. ...