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字符串常量池及字符串判等的总结。
最新文章
- Log4net入门(WCF篇)
- iOS中UIImageView的填充模式
- JSF JQUERY 使用datepicker
- 每天一个linux命令(54):sftp命令
- jQuery图表开源软件
- RHEL 5 安装phpqrcode生成二维码
- HttpClient 4.x 执行网站登录并抓取网页的代码
- C++11变长参数模板
- MVC 音乐商店 第 9 部分: 注册和结帐
- 用户输出表单处理php
- 伪元素::before和::after
- 2018/1/19 Netty学习笔记(一)
- Mysql简单笔记
- Yii2设计模式——静态工厂模式
- 1.Flask URL和视图
- UVA1601-The Morning after Halloween(双向BFS)
- Python字符串和列表的内置方法
- Springboot+MyBatis+mysql+jsp页面跳转详细示例
- BZOJ2226:LCMSum(欧拉函数)
- 查看Jira 使用的H2数据库 数据结构以及内容的方法
热门文章
- 跟你说个笑话,硕士毕业两年,月薪10k,天天面向CV编程
- 你的ES数据备份了吗?
- Linux引导过程和服务过程
- S3C2440—9.复制程序到SDRAM中执行
- AQS源码分析看这一篇就够了
- NOIP 模拟 $25\; \rm queen$
- NOIP 模拟 $17\; \rm 世界线$
- Docker运行PostgreSQL
- ASP.NET Core教程:ASP.NET Core中使用Redis缓存
- C++11 weak_ptr智能指针