Java面试题系列:将面试题中比较经典和核心的内容写成系列文章持续在公众号更新,可巩固基础知识,可梳理底层原理,欢迎大家持续关注【程序新视界】。本篇为面试题系列第2篇。

常见面试问题

下面代码中创建了几个对象?

new String("abc");

答案众说纷纭,有说创建了1个对象,也有说创建了2个对象。答案对,也不对,关键是要学到问题底层的原理。

底层原理分析

在上篇文章《面试题系列第1篇:说说==和equals的区别?你的回答可能是错误的》中我们已经提到,String的两种初始化形式是有本质区别的。

String str1 = "abc";  // 在常量池中String str2 = new String("abc"); // 在堆上

当直接赋值时,字符串“abc”会被存储在常量池中,只有1份,此时的赋值操作等于是创建0个或1个对象。如果常量池中已经存在了“abc”,那么不会再创建对象,直接将引用赋值给str1;如果常量池中没有“abc”,那么创建一个对象,并将引用赋值给str1。

那么,通过new String("abc");的形式又是如何呢?答案是1个或2个。

当JVM遇到上述代码时,会先检索常量池中是否存在“abc”,如果不存在“abc”这个字符串,则会先在常量池中创建这个一个字符串。然后再执行new操作,会在堆内存中创建一个存储“abc”的String对象,对象的引用赋值给str2。此过程创建了2个对象。

当然,如果检索常量池时发现已经存在了对应的字符串,那么只会在堆内创建一个新的String对象,此过程只创建了1个对象。

在上述过程中检查常量池是否有相同Unicode的字符串常量时,使用的方法便是String中的intern()方法。

public native String intern();

下面通过一个简单的示意图看一下String在内存中的两种存储模式。

上面的示意图我们可以看到在堆内创建的String对象的char value[]属性指向了常量池中的char value[]。

还是上面的示例,如果我们通过debug模式也能够看到String的char value[]的引用地址。

图中两个String对象的value值的引用均为{char[3]@1355},也就是说,虽然是两个对象,但它们的value值均指向常量池中的同一个地址。当然,大家还可以拿一个复杂对象(Person)的字符串属性(name)相同时的debug结果进行比对,结果是一样的。

深入问法

如果面试官说程序的代码只有下面一行,那么会创建几个对象?

new String("abc");

答案是2个?

还真不一定。之所以单独列出这个问题是想提醒大家一点:没有直接的赋值操作(str="abc"),并不代表常量池中没有“abc”这个字符串。也就是说衡量创建几个对象、常量池中是否有对应的字符串,不仅仅由你是否创建决定,还要看程序启动时其他类中是否包含该字符串。

升级加码

以下实例我们暂且不考虑常量池中是否已经存在对应字符串的问题,假设都不存在对应的字符串。

以下代码会创建几个对象:

String str = "abc" + "def";

上面的问题涉及到字符串常量重载“+”的问题,当一个字符串由多个字符串常量拼接成一个字符串时,它自己也肯定是字符串常量。字符串常量的“+”号连接Java虚拟机会在程序编译期将其优化为连接后的值。

就上面的示例而言,在编译时已经被合并成“abcdef”字符串,因此,只会创建1个对象。并没有创建临时字符串对象abc和def,这样减轻了垃圾收集器的压力。

我们通过javap查看class文件可以看到如下内容。

很明显,字节码中只有拼接好的abcdef。

针对上面的问题,我们再次升级一下,下面的代码会创建几个对象?

String str = "abc" + new String("def");

创建了4个,5个,还是6个对象?

4个对象的说法:常量池中分别有“abc”和“def”,堆中对象new String("def")和“abcdef”。

这种说法对吗?不完全对,如果说上述代码创建了几个字符串对象,那么可以说是正确的。但上述的代码Java虚拟机在编译的时候同样会优化,会创建一个StringBuilder来进行字符串的拼接,实际效果类似:

String s = new String("def");
new StringBuilder().append("abc").append(s).toString();

很显然,多出了一个StringBuilder对象,那就应该是5个对象。

那么创建6个对象是怎么回事呢?有同学可能会想了,StringBuilder最后toString()之后的“abcdef”难道不在常量池存一份吗?

这个还真没有存,我们来看一下这段代码:

@Test
public void testString3() {String s1 = "abc";String s2 = new String("def");String s3 = s1 + s2;String s4 = "abcdef";System.out.println(s3==s4); // false
}

按照上面的分析,如果s1+s2的结果在常量池中存了一份,那么s3中的value引用应该和s4中value的引用是一样的才对。下面我们看一下debug的效果。

很明显,s3和s4的值相同,但value值的地址并不相同。即便是将s3和s4的位置调整一下,效果也一样。s4很明确是存在于常量池中,那么s3对应的值存储在哪里呢?很显然是在堆对象中。

我们来看一下StringBuilder的toString()方法是如何将拼接的结果转化为字符串的:

@Override
public String toString() {// Create a copy, don't share the arrayreturn new String(value, 0, count);
}

很显然,在toString方法中又新创建了一个String对象,而该String对象传递数组的构造方法来创建的:

public String(char value[], int offset, int count) 

也就是说,String对象的value值直接指向了一个已经存在的数组,而并没有指向常量池中的字符串。

因此,上面的准确回答应该是创建了4个字符串对象和1个StringBuilder对象。

小结

我们通过一行创建字符串的代码逐步分析String对象的整个构建及拼接过程,了解了底层实现原理。是不是很有意思?当你掌握了这些底层基本知识,即便面试题的形式如何变化,你必定能一眼识破真相。

下篇文章,(读者提议)我们来讲讲Integer的比较的底层逻辑,欢迎持续关注。

本文首发来自微信公众号:程序新视界。一个软实力、硬技术同步学习的平台。

new string(abc)创建了几个对象_面试题系列第2篇:new String()创建几个对象?有你不知道的...相关推荐

  1. 以下创建了几个对象_面试题系列第2篇:new String()创建几个对象?

    Java面试题系列:将面试题中比较经典和核心的内容写成系列文章持续在公众号更新,可巩固基础知识,可梳理底层原理,欢迎大家持续关注[程序新视界].本篇为面试题系列第2篇. 常见面试问题 下面代码中创建了 ...

  2. 怎样在hdfs上创建多级目录文件夹_【Hadoop】如何在hdfs根目录下创建文件夹

    shell命令创建文件夹 启动hdfs,终端输入:start-dfs.sh 在hdfs中创建一个input文件夹:hadoop fs -mkdir /input/1 使用参数-p创建多级目录:hado ...

  3. java 字符串转对象_【Java】把一个对象转化为String字符串

    把一个对象obj转化为字符串,我有三个想法. obj + ""; obj.toString(); String.valueOf(obj); 这三种方法分别是我在三个阶段的用法. 最 ...

  4. python布尔测试对象_面试题十九期-测试开发面试题之python系列-这个中~

    坚持梦想 就算所有人都不支持你.这条路会很曲折,你也会一度认为是不是自己选错了,但只要坚持,就算最后没有成功,但努力了就不会有遗憾. 测试开发python系列面试题 01 单选题 1.下列哪个语句在P ...

  5. java s1=abc s2=abc s1==s2_经典问题:String s1 = abc 与 String s2 = new String(abc)的区别...

    这是以前刚学Java那会经常被问到的问题,并且也会经常出现在面试中.这个问题不仅仅只局限于Java,可以适用于其他大部分语言,正好最近有个小朋友在学编程,特此整理一下. String s1 = &qu ...

  6. 云端飘 String s=new String(abc)创建了几个对象?

    转自:http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html -------------------------------- ...

  7. String s=new String(abc)创建了2个对象的原因

    问题:String str=new String("abc"); 这行代码究竟创建了几个String对象呢? 相信大家对这道题并不陌生,答案也是众所周知的,2个. 接下来我们就从这 ...

  8. String str = new String(abc)创建了几个对象?结合源码解析

    String str = new String("abc")创建了几个对象?结合源码解析 首先,我们看一下jdk源码: 1 /** 2 * Initializes a newly ...

  9. Java:面试题:String s=new String(abc)创建了几个对象?

    String str=new String("abc");   紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢? 相信大家对这道题并不陌生,答案 ...

最新文章

  1. 小说里的lt什么意思_一般加杠杆是什么意思股市里?答案很简单
  2. php 动态输出图片尺寸,高并发下 php 输出图像对性能开销大不大?
  3. mapreduce 算法
  4. Cordova 本地项目创建方法
  5. Selenium-基础操作
  6. [js] 举例说明Object.defineProperty会在什么情况下造成循环引用导致栈溢出?
  7. 正面管教php_佛山市第三中学正面管教家长工作坊PHP分享会
  8. bearer token_四,接口认证方式:Bearer Token
  9. 数据科学包12-实例1:股票数据分析
  10. android带人脸识别码,Android自带的人脸识别
  11. hadoop、spark、hive、solr、es与YDB在车辆即席分析上的对比分析
  12. 金蝶shr动态列表展示自定义字段
  13. FSK过零检测技术软件实现
  14. python 一个例子解释全局变量和局部变量
  15. 力扣 460. LFU 缓存
  16. POJ3426 ACM Computer Factory——最大流(EK+输出路径)
  17. 移动Web MUI框架Switch开关自定义中文文字
  18. matlab - 特殊矩阵、矩阵求值、稀疏矩阵
  19. smartart连续块状流程图_只须四步让你的流程图更美
  20. Delphi -如何在 Delphi 链接 obj 文件

热门文章

  1. 【Elasticsearch】Elasticsearch的数据类型 (text、keyword、date、object、geo等)
  2. 【Kafka】Kafka Schema Registry 原理
  3. Mac OSX 平台安装 MongoDB
  4. SparkStreaming之updateStateByKey
  5. 【Kafka】Failed to send data to Kafka: Failed to allocate memory within the configured max blocking
  6. Flink 上传的Jar包去哪里了
  7. java.io.IOException: The temporary upload location [/tmp/tomcat.1XXXX] is not valid
  8. git : 上传大文件或者PDF或者二进制文件导致无法上传
  9. 04-windows下Orcale的启动
  10. 全网最全的 Java各类技术栈 架构图汇总(建议收藏)