String类的常见问题
String类的常见问题
1.判定定义为String类型的两个对象是否相等(1)
public class StringDemo01 {public static void main(String[] args) {String string01 = "zrt";String string02 = "zrt";System.out.println(string01 == string02); //trueSystem.out.println(string01.equals(string02)); //true}
}
分析:
在Java中“==”这个符号比较运算符,可以用来比较基本数据类型和引用数据类型是否相等
基本数据类型:比较的是值是否相等。
引用数据类型:比较的是两个对象的内存地址是否相等。
注意的是,String类型不属于八种基本数据类型,换句话说,String对象属于引用数据类型。将"zrt"同时赋值给了两个String类型的对象,而且两个String类的引用都是指向同一个地址,故第一个语句为“true”。
Object类提供的equals()方法,在String类(继承了Object类)中重写了equals()方法,通过JDK文档可知,此方法的解释为“将此字符串与指定的对象比较。当且仅当该参数不为null,并且是与此对象表示相同字符序列的 String对象时,结果才为true。”因为string01和strin02的值都为"zrt",具有相同字符序列,故第二个语句为“true”。
上述例子的内存图如下:
此过程大致如下:
- 运行先编译,将当前类StringDemo01.class文件加载进入内存的方法区。
- main方法压入栈内存。
- 常量池创建一个“zrt”对象,产生一个内存地址。
- 然后把“zrt”内存地址赋值给main方法里的成员变量string01,这个时候string01根据内存地址,指向了常量池中的“zrt”。
- 常量池有个特点,发现字符串对象“zrt”已经存在,就不在创建重复的对象。
- 运行到代码 String string02 =”zrt”, 由于常量池存在“zrt”,直接把“zrt”内存地址赋值给了string02。
- 所以,string01和string02 都指向了内存中同一个地址,所以两者是完全相同的。
2.内存中创建对象的个数
public class StringDemo02 {public static void main(String[] args) {String string01 = "zrt";}
}
上述例子在内存中创建了多少个对象呢?
答案便是:两个,一个堆内存,一个在常量池,而且堆内存对象是常量池对象的一个拷贝副本。
分析:我们都知道new这个关键词,new出来的对象都是存储在堆内存。“zrt”属于字符串,字符串属于常量,所以应该在常量池中创建,所以第一个创建的对象就是在常量池中的”zrt“。那为什么说堆内存对象是常量池的一个拷贝副本呢?从JDK1.6的文档中,可以看到构造方法String(String original) 的注释:”初始化一个新创建的 String
对象,使其表示一个与参数相同的字符序列“。也就是说,新创建的字符串就是该参数字符串的副本。换句话说,便是堆内存对象是常量池对象的一个拷贝副本。
上述例子的内存图如下:
3.判定定义为String类型的两个对象是否相等(2)
public class StringDemo03 {public static void main(String[] args) {String string01 = new String("zrt");String string02 = "zrt";System.out.println(string01 == string02); //falseSystem.out.println(string01.equals(string02)); //true}
}
分析:”==“比较的string01对象和string02对象的内存地址,由于string01指向的是堆内存的地址,string02看到“zrt”已经在常量池存在,就直接指向了常量池的内存地址,所以,第一个语句的输出结果false。第二个equals()放法比较,比较是两个字符串序列是否相等,由于都是“zrt”,故第二个语句的输出结果为true。
上述例子的内存图如下:
4.判定定义为String类型的两个对象是否相等(3)
public class StringDemo04 {public static void main(String[] args) {String string01 = "z" + "r" + "t";String string02 = "zrt";System.out.println(string01 == string02); //trueSystem.out.println(string01.equals(string02)); //true}
}
分析:“z”,”r”,”t”本来就是三个字符串常量,经过”+“符号进行拼接之后变成了字符串“zrt”,而“zrt”本身就是字符串常量(Java中有常量优化机制),所以会在常量池创建一个“zrt”的字符串常量对象。因此,在进行到string02=”zrt”的时候,因为常量池存在“zrt”,所以不会再创建“zrt”字符串对象。故无论是比较内存地址还是比较字符串序列,都相等,所以两个语句的输出结果都是true。
5.判定定义为String类型的两个对象是否相等(4)
public class StringDemo05 { public static void main(String[] args) {String string01 = "zrt";String string02 = "zrt";String string03 = string01 + "t";System.out.println(string02 == string03); //falseSystem.out.println(string02.equals(string03)); //true}
}
其中,第二个语句的输出结果为true,此处不再赘述。主要是为什么第一个语句的输出结果为什么是false呢?首先我们可以在JDK API1.6的文档中看到这样一句话:
Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过
StringBuilder
(或StringBuffer
)类及其append
方法实现的。字符串转换是通过toString
方法实现的,该方法由Object
类定义,并可被 Java 中的所有类继承。
分析:由上我们可知:任何数据和字符串进行加号(+)运算,最终得到是一个拼接而成新的字符串。上面注释说明了这个拼接的原理是由StringBuilder或者StringBuffer类和里面的append方法实现拼接,然后调用toString()把拼接的对象转换成字符串对象,最后把得到字符串对象的内存地址赋值给变量。
上述例子的内存图如下:
过程大致如下:
- 常量池创建“zr”对象,并将其内存地址值赋值给string01,所以string01指向了“zr”。
- 常量池创建“zrt”对象,并将其内存地址值赋值给string02,所以string02指向了“zrt”。
- 由于语句用的是“+”进行拼接string01和字符串对象“t”,所以是使用StringBuffer类的append()方法,得到了StringBuffel对象“zrt”(注意:现在还不是String对象),用0x01表示内存地址。
- 调用Object类的toString()方法,将StringBuffer对象转换成String对象,用0x01表示内存地址。
- 将String对象的内存地址(0x02)赋值给string03。所以进行“==”判断的输出结果为false,因为内存地址不同。
6.总结
这篇文章,是我在学习String类的时候遇到一个小疑惑,做成笔记加深印象,重点就是理解JDK API一些注解和原理、内存图。通过画内存图也可以帮助我们理解其中的原理。
String类的常见问题相关推荐
- java的知识点15——String基础、String类和常量池、String类常用的方法、字符串相等的判断、组合模式
String基础 1. String类又称作不可变字符序列. 2. String位于java.lang包中,Java程序默认导入java.lang包下的所有类. 3. Java字符串就是Unicode ...
- C++ 笔记(22)— STL string 类(字符串赋值、访问、拼接、查找、翻转、大小写转换)
1. 实例化和赋值 STL string #include <string> #include <iostream>int main () {using namespace s ...
- java string改变的影响_为什么Java的string类要设成immutable(不可变的)
最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类 ...
- C++——String类超详细介绍
(欢迎及时指正错误!谢谢) STL的含义:标准模板库 STL的内容: 容器:数据的仓库 算法:与数据结构相关的算法.通用的算法(和数据结构无关) 注:熟悉常用的算法 sort reverse 迭代器 ...
- 标准C++中的string类的用法总结
相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...
- c++ string replace_JAVA应用程序开发之String类常用API
[本文详细介绍了JAVA应用开发中的String类常用API,欢迎读者朋友们阅读.转发和收藏!] 1 基本概念 API ( Application Interface 应用程序接口)是类中提供的接口, ...
- javascript:为string类添加三个成员,实现去左,右,及所有空格
<script language="JavaScript"> //此处为string类添加三个成员 String.prototype.Trim = func ...
- 字符串(string类)
[1]String类基本函数如何实现? 示例代码如下: 1 #include<iostream> 2 #include<assert.h> 3 #include<stri ...
- 交换变量和String类初始化:JAVA入门基础
本文主要介绍了变量交换.String类初始化.字符串的基本操作.变量交换详解介绍了两个变量是如何交换的,通过例子理解这个用法. 一.交换变量 1.什么是交换变量 例如用户输入a.b的值分别3,9的整数 ...
最新文章
- 芯片初创公司一亿融资可以烧多久
- VMware15克隆虚拟机Centos
- java中打开的线程怎么关闭_[求助] 用线程怎么关闭运行中的窗口
- Python类的部分
- js复制数据IE,FF..浏览器兼容
- VTK:PolyData之CellLocatorVisualization
- PHP与SQL注入攻击
- python max取下标_Python 变量类型总结
- 怎么把打开方式改回计算机程序,电脑打开方式改变了,怎么还原
- redis五种数据类型的使用场景
- 【苹果相册推送】excerantione system.out.printlni 家哦,==电子电子邮件
- 带你快速入门AXI4总线--AXI4-Stream篇(1)----AXI4-Stream总线
- C#测试调用PaddleSharp模块识别图片文字
- 沉病孩子留遗嘱 父疏申请接济劫持红十字员农
- 【附源码】计算机毕业设计SSM企业合同管理系统
- 计算机教学音乐,计算机音乐的教学和应用研究
- 如何加载3D模型(odj文件和mtl文件)
- iNFTnews | 呵护“雪山精灵”,42VERSE“数字生态保护”公益项目即将盛启
- 紧随小米2:LG Optimus G也用高通四核APQ8064
- python对象的生命周期_python对象的生命周期
热门文章
- 微信公众号聊天室 私聊功能演示
- 云呐|什么是容灾备份一体机?
- Django2.0——Form组件简单总结
- Dual Self-Attention Network (DSANet)
- linux tail 命令详解,Linux下如何使用tail命令指南
- 面试经历(签约华为,违约华为,签约移动)
- 公共关系礼仪实务章节测试题——公共关系的类型(三)
- 使用Java模拟Web端的POST或GET请求,实现自动化操作:加密狗烧制技术详解
- 2022年塔式起重机司机(建筑特殊工种)考题及在线模拟考试
- 运动员svg图标素材推荐 精品 小众