关于一段有趣代码引出的String创建对象的解释
通常来说,我们认为hashCode不相同就为不同的对象。就这样由一段代码引发了一场讨论,代码如下:
@Test
public void stringCompare() {
String s1 = "test";
String s2 = "test";
String s3 = new String("test");
String s4 = new String("test"); System.out.println("value compare:");
System.out.println("s1.equals(s2):" + s1.equals(s2));
System.out.println("s2.equals(s3):" + s2.equals(s3));
System.out.println("s3.equals(s4):" + s3.equals(s4));
System.out.println("s1==s2:" + (s1 == s2));
System.out.println("s2==s3:" + (s2 == s3));
System.out.println("s3==s4:" + (s3 == s4)); System.out.println("hashCode compare:");
System.out.println("s1~s2:"+ (s1.hashCode() == s2.hashCode()));
System.out.println("s2~s3:"+ (s2.hashCode() == s3.hashCode()));
System.out.println("s3~s4:"+ (s3.hashCode() == s4.hashCode()));
}
有兴趣的话先猜一猜上面的打印结果。这段代码可以很好的说明String在创建对象的特殊性。
运行上面的代码结果为:
value compare:
s1.equals(s2):true
s2.equals(s3):true
s3.equals(s4):true
s1==s2:true
s2==s3:false
s3==s4:false
hashCode compare:
s1~s2:true
s2~s3:true
s3~s4:true
猜对了吗?会不会有点奇怪,接下来我将逐一说明,并解释String创建对象的机理。
首先我们知道equals的比较是两个对象的值是否相同,这个毋庸置疑,我们都赋值“test”,所以结果必然是三个true,这一点没有什么问题。
然后看“==”的比较,“==”是比较物理地址时候相同,也是比较是否为同一对象的手段。结果是s1和s2是true,后面的两个比较是false,这就说明s1和s2指向的是同一块地址。s3和s4是通过new出来的对象,我们知道new通常是开辟了新空间,而直接赋值是引用赋值。所以这一点也基本上没有什么问题,这就解释了s2==s3:false,s3==s4:false。
最后同通常我们认为hashCode不同就是不同的对象,但是这四个对象的hashCode是全部相同的。这似乎和使用"=="比较有点违背。但其实并不矛盾,必须明确一点是hashCode和物理地址没有必然的关系。之所以是这样,是因为Sting在创建对象时的机制有所不同。
重点:
JVM为String类型提供了一个字符池(jdk7之前在permgen,jdk7之后也是堆里)。每次在创建对象时,都会现在字符池中查找该字符串是否存在。这是大的前提逻辑,现在我们就一下几种情况分别说明:
1.创建一个对象 String s1 = new String("我是字符串"),遵循大逻辑,先在pool中检索,但其实无论pool中有没有,都会创建一个新的对象。不同的是:
a.pool中没有:
在pool中添加一个新的对象“我是字符串”,也就是说这里创建了两个对象,除了s1这个对象外,在pool中还创建了一个对象;这个时候创建s2 = "我是字符串"; 同样检查pool,发现已有,那s2指向pool中的“我是字符串”的地址。
b.pool中有:
则只创建一个对象及就是s1。这个时候创建s2= “我是字符串”;同样会检查pool发现存在,那s2直接指向pool中的地址。
2.创建一个String s1 = "我是字符串",遵循大逻辑,先在pool中检索:
a.pool中没有:
在pool中没有检索到“我是字符串”,那么在pool中添加一个字符串对象“我是字符串”,然后s1指向pool中的地址。这个时候如果创建String s2 = new String("我是字符串");检测pool中已有,同1.b中创建s1过程。
b.pool中有:
在pool中检索到,s1直接指向pool中的地址,如果创建String s2 = new String("我是字符串");同1.b中创建s1过程。
注意:
1.hashCode实际与物理地址没有必然关系,只是习惯上我们可以用hashCode判断是否为同一对象。
2.pool也是有大小限制的,对于不用的字符串对象,垃圾机器人会回收,释放空间。
关于一段有趣代码引出的String创建对象的解释的更多相关文章
- 一段C++代码想到的问题
今天在学习<Unix环境高级编程>,第七章进程环境给出了一个进程的内存分布示意图,从下往上依次为“正文段->初始化数据->未初始化数据(默认初始化为0)->堆(从低地址到 ...
- 通过Java字节码发现有趣的内幕之String篇(上)(转)
原文出处: jaffa 很多时候我们在编写Java代码时,判断和猜测代码问题时主要是通过运行结果来得到答案,本博文主要是想通过Java字节码的方式来进一步求证我们已知的东西.这里没有对Java字节码知 ...
- c#代码 天气接口 一分钟搞懂你的博客为什么没人看 看完python这段爬虫代码,java流泪了c#沉默了 图片二进制转换与存入数据库相关 C#7.0--引用返回值和引用局部变量 JS直接调用C#后台方法(ajax调用) Linq To Json SqlServer 递归查询
天气预报的程序.程序并不难. 看到这个需求第一个想法就是只要找到合适天气预报接口一切都是小意思,说干就干,立马跟学生沟通价格. 不过谈报价的过程中,差点没让我一口老血喷键盘上,话说我们程序猿的人 ...
- java如何从一段html代码中获取图片的src路径
java如何从一段html代码中获取图片的src路径 package com.cellstrain.icell.Test; import java.util.ArrayList;import java ...
- 一段小代码秒懂C++右值引用和RVO(返回值优化)的误区
关于C++右值引用的参考文档里面有明确提到,右值引用可以延长临时变量的周期.如: std::string&& r3 = s1 + s1; // okay: rvalue referen ...
- C# 一段绘图代码 在form_load事件不能显示图
今天无意将一段绘图代码 写在form_load事件了,结果不能显示绘图.(代码:Graphics g = this.CreateGraphics();Pen pen = new Pen(Color.R ...
- 【转】可执行程序包括BSS段、数据段、代码段
可执行程序包括BSS段.数据段.代码段(也称文本段). 一.BSS BSS(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域.特点是:可 ...
- 五个数据段之代码段、数据段、BSS、栈、堆
继上文讲完了对内存管理的一些知识,下面笔者再对上篇文章的内容加以拓展,那么我们今天就来说一说5个数据段 五个数据段 进程(执行的程序)会占用一定数量的内存,它或是用来存放磁盘载入的程序代码,或是存放取 ...
- 数据段、代码段、堆栈段、BSS段的区别
进程(执行的程序)会占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等.不过进程对这些内存的管理方式因内存用 途 不一而不尽相同,有些内存是事先静态分配和统一回收的 ...
随机推荐
- javaweb新手学习之Tomcat
一.Tomcat服务器常见启动问题: (1).Java_home环境变量,由于tomcat服务器的bin目录中的一些jar文件必须使用到java类库,所以必须先配置Java_home环境变量. (2) ...
- 029-实现阿里云主机VPC网络SDN结构
- VB中IIF函数
IIf 函数语法:IIf(表达式, 真值部分, 假值部分)根据表达式的值,表达式为真时,返回真值部分,表达式为假时,返回假部分.如:iif(a>0, "对","错& ...
- 用element-ui进行文件的上传
在进项的项目中,我使用vue配合element搭建的项目,现在需要用到上传文件的写法!现在列举下我的项目中所使用的上传文件的方法! <el-upload style="display: ...
- Codeforces Round #573 (Div. 2) D. Tokitsukaze, CSL and Stone Game (博弈,思维)
D. Tokitsukaze, CSL and Stone Game time limit per test1 second memory limit per test256 megabytes in ...
- boost::regex
https://blog.51cto.com/liam2199/2108548 正则表达式
- 安装mod_rpaf让apache获取访客真实IP
安装mod_rpaf让apache获取访客真实IP 安装mod_rpaf让apache获取访客真实IP 作者:朱 茂海 /分类:Apache 字号:L M S mod_rpaf是apache ...
- C++ GUI Qt4学习笔记03
C++ GUI Qt4学习笔记03 qtc++spreadsheet文档工具resources 本章介绍创建Spreadsheet应用程序的主窗口 1.子类化QMainWindow 通过子类化QM ...
- 【NOIP2016提高A组模拟7.17】锦标赛
题目 403机房最近决定举行一场锦标赛.锦标赛共有N个人参加,共进行N-1轮.第一轮随机挑选两名选手进行决斗,胜者进入下一轮的比赛,第二轮到第N-1轮再每轮随机挑选1名选手与上一轮胜利的选手决斗,最后 ...
- 使用idea对XML的增删改查
XML:是一种可扩展标记性的语言,与java语言无关,它可以自定义标签. 1.首先需要到导入Dom4j架包,与自己所时候的ide关联 2.编写自己的xml文件,入上图所示(里面的所有元素及元素中的属性 ...