String是否相等、new的时候创建了几个对象等问题详解
问题一
这段代码创建了几个对象?
String str1 = new String("aa");
答案是两个
“aa”对象和String对象
Java代码在编译成Class文件之后,Class文件中包含以下内容

其中有一项是常量池
常量池在Class文件被加载的时候,会被加载进内存中的方法区中的运行时常量池,而运行时常量池里就包括字符串常量池,Class文件中的字符串在类加载时就会加载到字符串常量池中去

不过在周志明老师在深入java虚拟机中有说到,到了JDK1.7时,字符串常量池就被移出了方法区,转移到了堆里了。当然这并不影响我们之后的解读
而代码
String str1 = new String("aa");
中的"aa"就是被加载进去的字符串,我们可以看看Class文件

(1). 这里的aa在之后类加载的时候
会在字符串常量池里创建一个 "aa"对象,这是第一个对象
(2). 类加载完成了之后,那就要开始正式执行代码了
执行该行代码时new一个"aa"的String对象存放在Java堆中,这是第二个对象
(3). 创建完第二个对象后,虚拟机栈上的str1将会指向第二个对象,也就是堆上的对象
问题二
结果是true还是false?
String str1 = new String("aa");
String str2 = "aa";
System.out.println(str1 == str2);
答案很明显是false,因为两个变量指向的地址不同,一个指向字符串常量池,一个指向堆上的对象,而==比较的就是地址。
问题三
那这个的结果是true还是false?
String str1 = new String("aa");
str1.intern();
String str2 = "aa";
System.out.println(str1 == str2);
首先我们来了解一下intern方法
intern的处理是 先判断字符串常量是否在字符串常量池中,如果存在直接返回该常量,如果没有找到,说明该字符串常量在堆中,则处理是把堆区该对象的引用加入到字符串常量池中,以后别人拿到的是该字符串常量的引用,实际存在堆中。
也就是说现在字符串常量池中的"aa"实际上是指向堆上的String对象的?
所以结果是true?
并不是,结果还是false
我们在之前问题一中,
String str1 = new String("aa");
这段代码创建了两个对象,而第一个就是在字符串常量池中的,而intern方法在判断时会发现字符串常量池中已经存在"aa"对象了,所以它就不用把字符串常量池中添加一个指向堆上的String对象的地址了
所以最后intern方法只是返回了"aa"对象,并没有做任何修改
所以还是str1指向堆,str2指向字符串常量池,结果为false
那要怎么样才能true?
问题四
String str3 = new String("a") + new String("a");
str3.intern();
String str4 = "aa";
System.out.println(str3 == str4);
这里打印的结果就是true了
这里的str3生成的方式不再是new String(“aa”);
而是new String(“a”) + new String(“a”);拼接起来的方式,因此在编译后,Class文件中的常量池写入的是"a"对象而不是"aa"对象,如下图:

因此intern方法在判断时会发现字符串常量池中并没有"aa"对象,
于是它就把堆中String对象的引用加入到字符串常量池中
之后创建str4的时候,str4就会先在字符串常量池中先查找有没有"aa",于是它找到了intern放入的引用,并把这个引用赋给str4
所以str3和str4都是同一个引用,str3==str4,为true
问题五
那么这段代码又创建了几个对象?
String str3 = new String("a") + new String("a");
答案是五个
因为使用+号的String字符串拼接,底层其实都是先创建一个StringBuilder对象,然后调用append方法把要+的字符串都append进去,最后toString创建一个新的String对象如下图:

红色的地方就是new出来对象的语句,而绿色则是两次append
四个红色一共四个对象,再加上字符串常量池上创建的"a"对象,一共五个
这也正是为什么阿里巴巴代码规范中不建议在for循环里使用+号拼接字符串
String str1 = "aaa";
String str2 = "bbb";
String str4 = str1 + str2;
这个的String str4 = str1 + str2;创建了两个对象,StringBuilder和toString时生成的String对象
那下面这段呢?是"aaa"对象加"bbb"对象加StringBuilder和toString时生成的String对象一共四个对象吗?
String str5 = "aaa" + "bbb";
很可惜这段只创建了1个对象
java编译器在编译这段的时候做了优化,实际上"aaa"+"bbb"会先拼接成"aaabbb"之后才开始编译,也就是说这段代码等于是String str5 = "aaabbb"
如下图:(code里面没有任何new操作)

String是否相等、new的时候创建了几个对象等问题详解的更多相关文章
- String s="a"+"b"+"c"+"d";创建了几个对象?
对于如下代码: package reviewTest; /** * @ClassName: StringTest * @Description: 测试String的字符串相加优化 * @author ...
- Java经典设计模式之五大创建型模式(附实例和详解)
一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...
- Java设计模式之五大创建型模式(附实例和详解)
一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...
- (转)Java经典设计模式(1):五大创建型模式(附实例和详解)
原文出处: 小宝鸽 一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代 ...
- MongoDB创建数据库和集合命令db.createCollection详解(转)
切换/创建数据库 use yourDB; 当创建一个集合(table)的时候会自动创建当前数据库 完整的命令如下:db.createCollection(name, {capped: <Boo ...
- Mat矩阵(图像容器)创建及CV_8UC1、CV_8UC2等参数详解
CV_<bit_depth>(S|U|F)C<number_of_channels> 1--bit_depth---比特数---代表8bite,16bites,32bites, ...
- 42.QT-QSqlQuery类操作SQLite数据库(创建、查询、删除、修改)详解
Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作.这里我们所说的“平台 独立”,既包括操作系统平台,也包括各个数据库平台,Qt支持以下几种数据库: QT自带SQLITE数据库, ...
- Jmeter(二) - 从入门到精通 - 创建测试计划(Test Plan)(详解教程)
1.简介 上一篇中宏哥已经教你把JMeter的测试环境搭建起来了,那么这一篇我们就将JMeter启动起来,一睹其芳容,首先宏哥给大家介绍一下如何来创建一个测试计划(Test Plan). 2.创建一个 ...
- Linux下Qt创建共享库与链接共享库详解
随着程序写的逐渐变多,或多或少的我们都会使用别人写好的库:或者我们不想让别人看到我们的一些核心程序,可以将核心程序封装成库.本次和大家分享的是在Ubuntu下使用Qt生成共享库以及在Qt中链接共享库的 ...
随机推荐
- 基于springboot1.5.9整合shiro时出现静态文件找不到的问题
开门见山吧,上午对shiro进行整合了下,因为之前使用ssm框架对shiro框架整合过,所以觉得使用springboot再次对shiro框架进行整合也是没啥问题,但最后整合完之后,使用thymelea ...
- 第八次——非确定的自动机NFA确定化为DFA
NFA 确定化为 DFA 子集法: f(q,a)={q1,q2,…,qn},状态集的子集 将{q1,q2,…,qn}看做一个状态A,去记录NFA读入输入符号之后可能达到的所有状态的集合. 步骤: 1. ...
- Centos7 U盘安装
以下内容来自 https://www.cnblogs.com/Hello-java/p/8628917.html 和 https://blog.csdn.net/fiiber/article/deta ...
- 添加谷歌拓展程序 vue.js devtools过程中的问题
在用vue做项目过程中,需要用到vue.js devtools,在从github上面clone下来代码,然后再npm install ,过程报错,然后更新npm包也是会有问题,以下是install的问 ...
- Redis系列二 - 数据结构
前言 redis作为我们开发的一大神器,我们接触肯定不会少,但是很多同学也许只会存储String类型的值,这是非常不合理的.在这里,将带大家认识Redis的5中数据结构. 1.问:Redis有那些数据 ...
- JS反爬绕过思路之--谷歌学术镜像网链接抓取
首先,从问题出发: http://ac.scmor.com/ 在谷歌学术镜像网收集着多个谷歌镜像的链接.我们目标就是要把这些链接拿到手. F12查看源码可以发现,对应的a标签并不是我们想要的链接,而是 ...
- MySQL字符集不一致导致性能下降25%,你敢信?
故事是这样的: 我在对MySQL进行性能测试时,发现CPU使用率接近100%,其中80%us, 16%sys,3%wa,iostat发现磁盘iops2000以下,avgqu-sz不超过3,%util最 ...
- C语言程序设计(六) 循环控制结构
第六章 循环控制结构 循环结构:需要重复执行的操作 被重复执行的语句序列称为循环体 计数控制的循环 条件控制的循环 当型循环结构 直到型循环结构 for while do-while while(循环 ...
- burpsuit的安装和简单使用
一.burpsuit的环境搭建 Burp Suite可以说是Web安全工具中的瑞士军刀,打算写几篇Blog以一个小白的角度去学习Burp Suite(简称BP),会详细地说一下的用法,说明一下每一个部 ...
- [CSP初赛] 组合数学的三个技巧以及从另一方面思考组合类问题
也不知道老师讲不讲 话说好久没有水博客了,看了一点\(python\)然后就去搞文化课了 正好网课讲到组合数学,然后觉得还蛮难的(其实是我变菜了),就想到了以前的\(csp\)的组合数学基础 果然被我 ...
