通常来说,我们认为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创建对象的解释的更多相关文章

  1. 一段C++代码想到的问题

    今天在学习<Unix环境高级编程>,第七章进程环境给出了一个进程的内存分布示意图,从下往上依次为“正文段->初始化数据->未初始化数据(默认初始化为0)->堆(从低地址到 ...

  2. 通过Java字节码发现有趣的内幕之String篇(上)(转)

    原文出处: jaffa 很多时候我们在编写Java代码时,判断和猜测代码问题时主要是通过运行结果来得到答案,本博文主要是想通过Java字节码的方式来进一步求证我们已知的东西.这里没有对Java字节码知 ...

  3. c#代码 天气接口 一分钟搞懂你的博客为什么没人看 看完python这段爬虫代码,java流泪了c#沉默了 图片二进制转换与存入数据库相关 C#7.0--引用返回值和引用局部变量 JS直接调用C#后台方法(ajax调用) Linq To Json SqlServer 递归查询

    天气预报的程序.程序并不难. 看到这个需求第一个想法就是只要找到合适天气预报接口一切都是小意思,说干就干,立马跟学生沟通价格. ​ ​不过谈报价的过程中,差点没让我一口老血喷键盘上,话说我们程序猿的人 ...

  4. java如何从一段html代码中获取图片的src路径

    java如何从一段html代码中获取图片的src路径 package com.cellstrain.icell.Test; import java.util.ArrayList;import java ...

  5. 一段小代码秒懂C++右值引用和RVO(返回值优化)的误区

    关于C++右值引用的参考文档里面有明确提到,右值引用可以延长临时变量的周期.如: std::string&& r3 = s1 + s1; // okay: rvalue referen ...

  6. C# 一段绘图代码 在form_load事件不能显示图

    今天无意将一段绘图代码 写在form_load事件了,结果不能显示绘图.(代码:Graphics g = this.CreateGraphics();Pen pen = new Pen(Color.R ...

  7. 【转】可执行程序包括BSS段、数据段、代码段

    可执行程序包括BSS段.数据段.代码段(也称文本段). 一.BSS BSS(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域.特点是:可 ...

  8. 五个数据段之代码段、数据段、BSS、栈、堆

    继上文讲完了对内存管理的一些知识,下面笔者再对上篇文章的内容加以拓展,那么我们今天就来说一说5个数据段 五个数据段 进程(执行的程序)会占用一定数量的内存,它或是用来存放磁盘载入的程序代码,或是存放取 ...

  9. 数据段、代码段、堆栈段、BSS段的区别

    进程(执行的程序)会占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等.不过进程对这些内存的管理方式因内存用 途 不一而不尽相同,有些内存是事先静态分配和统一回收的 ...

随机推荐

  1. PAT Basic 1014 福尔摩斯的约会 (20 分) Advanced 1061 Dating (20 分)

    大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm.大侦探很快就明白了,字条上奇 ...

  2. 长沙理工大学第十二届ACM大赛-重现赛C 安卓图案解锁 (模拟)

    链接:https://ac.nowcoder.com/acm/contest/1/C来源:牛客网 安卓图案解锁 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言 ...

  3. Stack Overflow 推荐编程书单

    Stack Overflow 推荐编程书单   1 Working Effectively with Legacy Code Michael C. Feathers 修改代码是每一位软件开发人员的日常 ...

  4. 超好用的input模糊搜索 jq模糊搜索,

    上来先展示效果:默认展示效果: 输入内容: 上代码: css部分: <style type="text/css"> * { padding:; margin:; } h ...

  5. SpringToolSuit(STS)添加了Lombok后仍然报错

    参见这篇博客 https://blog.csdn.net/qq_27442469/article/details/90612918 上面步骤做完后,在项目右键->Maven->Update ...

  6. vue面试题专题

    1,v-if和v-show的作用是什么?有什么区别? v-if:        创建---删除,没有元素.切换开销大.适合不频繁切换的情况用. 例子:制作搜索框,导航栏和搜索框重叠的两个框,点击搜索图 ...

  7. ES6数据结构Set、Map

    一.Set数据结构 Set是无序的不可重复的多个value的集合体,Set结构是类似于数组结构,但是Set中的值都不能重复 常用的属性和方法 size:返回set实例的成员总数 add():添加某个值 ...

  8. for-in语句和with语句、break和continue语句

    for-in语句 for-in语句是一种精准迭代语句,可以用来枚举对象的属性,用以遍历一个对象的全部属性. for…in声明用于对数组或者对象的属性进行循环操作: for…in循环中的代码每执行一次, ...

  9. jsp格工化日期

    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> .当后台传过来的时 ...

  10. 大文件上传-大视频上传,T级别的,求解决方案

    第一点:Java代码实现文件上传 FormFile file = manform.getFile(); String newfileName = null; String newpathname =  ...