问题一

这段代码创建了几个对象?

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的时候创建了几个对象等问题详解的更多相关文章

  1. String s="a"+"b"+"c"+"d";创建了几个对象?

    对于如下代码: package reviewTest; /** * @ClassName: StringTest * @Description: 测试String的字符串相加优化 * @author ...

  2. Java经典设计模式之五大创建型模式(附实例和详解)

    一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...

  3. Java设计模式之五大创建型模式(附实例和详解)

    一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...

  4. (转)Java经典设计模式(1):五大创建型模式(附实例和详解)

    原文出处: 小宝鸽 一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代 ...

  5. MongoDB创建数据库和集合命令db.createCollection详解(转)

    切换/创建数据库 use yourDB;  当创建一个集合(table)的时候会自动创建当前数据库 完整的命令如下:db.createCollection(name, {capped: <Boo ...

  6. Mat矩阵(图像容器)创建及CV_8UC1、CV_8UC2等参数详解

    CV_<bit_depth>(S|U|F)C<number_of_channels> 1--bit_depth---比特数---代表8bite,16bites,32bites, ...

  7. 42.QT-QSqlQuery类操作SQLite数据库(创建、查询、删除、修改)详解

    Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作.这里我们所说的“平台 独立”,既包括操作系统平台,也包括各个数据库平台,Qt支持以下几种数据库: QT自带SQLITE数据库, ...

  8. Jmeter(二) - 从入门到精通 - 创建测试计划(Test Plan)(详解教程)

    1.简介 上一篇中宏哥已经教你把JMeter的测试环境搭建起来了,那么这一篇我们就将JMeter启动起来,一睹其芳容,首先宏哥给大家介绍一下如何来创建一个测试计划(Test Plan). 2.创建一个 ...

  9. Linux下Qt创建共享库与链接共享库详解

    随着程序写的逐渐变多,或多或少的我们都会使用别人写好的库:或者我们不想让别人看到我们的一些核心程序,可以将核心程序封装成库.本次和大家分享的是在Ubuntu下使用Qt生成共享库以及在Qt中链接共享库的 ...

随机推荐

  1. vue路由传参页面刷新参数丢失问题解决方案

    最近项目中涉及到跨页面传参数和后台进行数据交互,看到需求之后第一反应就是用路由传参来解决:Vue中给我们提供了三种路由传参方式,下面我们一个一个的来看一下: 方法一:params传参: this.$r ...

  2. React Native Debug原理浅析

    第一次在segmentfault写博客,很紧张~~~公司项目上ReactNative,之前也是没有接触过,所以也是一边学习一边做项目了,最近腾出手来更新总结了一下RN的Debug的一个小知识点,不是说 ...

  3. VUE实现Studio管理后台(完结):标签式输入、名值对输入、对话框(modal dialog)

    一周的时间,几乎每天都要工作十几个小时,敲代码+写作文,界面原型算是完成了,下一步是写内核的HTML处理引擎,纯JS实现.本次实战展示告一段落,等RXEditor下一个版本完成,再继续分享吧.剩下的功 ...

  4. 复制url事故:出现特殊的字符%E2%80%8B

    复制url事故:出现特殊的字符%E2%80%8B 问题:直接其他地方复制过来的中文字进行网页搜索.或者中文字识别排序等情况的,会出现搜索不到的情况. 解决方法:可能存在复制源里面的文字带了空白url编 ...

  5. MATLAB神经网络(6) PID神经元网络解耦控制算法——多变量系统控制

    6.1 案例背景 6.1.1 PID神经元网络结构 PID神经元网络从结构上可以分为输入层.隐含层和输出层三层,$n$个控制量的PID神经元网络包含$n$个并列的相同子网络,各个子网络间既相互独立,又 ...

  6. 微博立场检测 60分Baseline

    AI研习社最近举办了一个比赛--微博立场检测,实际上就是一个NLP文本分类的比赛 Baseline-FastText 我的Baseline方法用的是pkuseg分词+FastText,最好成绩是60, ...

  7. 前端要了解的seo

    一.搜索引擎工作原理 当我们在输入框中输入关键词,点击搜索或查询时,然后得到结果.深究其背后的故事,搜索引擎做了很多事情. 在搜索引擎网站,比如百度,在其后台有一个非常庞大的数据库,里面存储了海量的关 ...

  8. Spark实战--寻找5亿次访问中,访问次数最多的人

    问题描述 对于一个大型网站,用户访问量尝尝高达数十亿.对于数十亿是一个什么样的概念,我们这里可以简单的计算一下.对于一个用户,单次访问,我们通常会记录下哪些数据呢? 1.用户的id 2.用户访问的时间 ...

  9. try_catch_return

    1.情况一(try中有return,finally中没有return): public class TryTest{ public static void main(String[] args){ S ...

  10. 【Weiss】简单说一下这一分类下的东西

    主要是学习资料<数据结构与算法分析>(Weiss)的习题 除去习题外,每一章主要用到的数据结构先会写一个版本放上来,包括数据结构代码与测试用代码 这种先行上传的代码只具有基本的功能,毕竟一 ...