这个问题相信每个学习java的同学都不陌生,作为一个经典的面试题,到现在工作这么多年了我真是认为挺操蛋的一个问题,在网上到现在你仍然可以看见很多讨论这个问题的人,其中不乏工作很多年的人都有争论,我认为还是有必要来说一说这个问题的。

从方法区说起

常量池存在于方法区,而方法区在jdk1.7版本前后改变比较大,所以还是先来说说方法区的演变。

在jdk1.7版本之前,常量池存在于方法区,方法区是堆的一个逻辑部分,他有一个名字叫做非堆

1.7版本把字符串常量池放到了堆中。

而在1.8以后,则是移除了永久代,方法区概念保留,方法区的实现改为了元空间,常量池还是在堆中。

为什么要说方法区的改变,只是为了文章接下来的内容不会由于JDK的版本而产生分歧,接下来内容都会以jdk1.8版本作为基础来讨论。

String s = new String("xyz");

先来一段代码

public class Test {
public static void main(String[] args) {
String s = "xyz";
}
}

接着我们javac编译代码,然后用javap来反编译,执行javap -c Test

从结果来看,ldc命令在常量池中创建了一个"xyz"的对象,然后把他推至操作数栈顶,然后astore保存到局部变量,return返回。

接着看第二段面试题中的代码

public class Test {
public static void main(String[] args) {
String s = new String("xyz");
}
}

同样反编译分析

很明显,我们看到new 创建了一个String对象,同时ldc在常量池中创建了"xyz"字符串对象,之后invokespecial执行构造函数,astore_1赋值,return返回。

通过以上两个例子,可以知道String s = new String("xyz"); 创建了2个对象,而有些答案说的3个对象,则是把引用s也算作一个对象。

还有答案说xyz存在就创建了2个,不存在就创建了3个(包含引用s),再来测试一下。

public class Test {
public static void main(String[] args) {
String s = "xyz";
String s2 = new String("xyz");
}
}

从这里,很明显的发现这就是我们例子1和2的一个结合,但是注意两次ldc后面的#2,#号代表着索引,说明第二次new String("xyz")的时候并没有重新创建xyz对象。

一些常见的指令助记符含义:

  1. nop, 什么都不做。
  2. aconst_null,将 null 推送至栈顶。
  3. iconst_i(变量数字),将 int 型 i 推送至栈顶。同理有lconst_0,fconst_0这种你应该知道什么意思了
  4. ldc,将 int,float 或 String 型常量值从常量池中推送至栈顶。
  5. iload,将指定的 int 型局部变量推送至栈顶。
  6. istore,将栈顶 int 型数值存入指定局部变量。同理astore_i代表将栈顶引用型数值存入第i个局部变量。
  7. dup,复制栈顶数值并将复制值压入栈顶。
  8. invokevirtual,调用实例方法。
  9. invokespecial,调用超类构造方法,实例初始化方法,私有方法。
  10. invokestatic,调用静态方法。
  11. invokeinterface,调用接口方法。
  12. invokedynamic,调用动态链接方法。
  13. new,创建一个对象,并将其引用值压入栈顶。

总结

到底创建了几个对象呢?

  1. 如果xyz不存在,引用算对象的话,那就是3个

  2. 如果xyz不存在,引用不算对象的话,那就是2个

  3. 如果xyz存在,引用算对象的话,那就是2个

  4. 如果xyz存在,引用不算对象的话,那就是1个

当然,我认为引用肯定是不算对象的,最终答案应该是1或者2个,这个面试题说实话不应该出现在初级面试题里。

另外,如果你不看不懂反编译后的字节码指令,关注公众号回复关键字111可获取《Java虚拟机规范》电子书。

工作10年后,再看String s = new String("xyz") 创建了几个对象?的更多相关文章

  1. String s = new String("xyz");创建了几个对象?

    两个或一个都有可能 . ”xyz”对应一个对象,这个对象放在字符串常量池,常量”xyz”不管出现多少遍,都是常量池中的那一个. new String每写一遍,就创建一个新的对象,它使用常量”xyz”对 ...

  2. String是否相等、new的时候创建了几个对象等问题详解

    问题一 这段代码创建了几个对象? String str1 = new String("aa"); 答案是两个 "aa"对象和String对象 Java代码在编译 ...

  3. [转] 请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧

    这帖是用来回复高级语言虚拟机圈子里的一个问题,一道Java笔试题的. 本来因为见得太多已经吐槽无力,但这次实在忍不住了就又爆发了一把.写得太长干脆单独开了一帖. 顺带广告:对JVM感兴趣的同学们同志们 ...

  4. 请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧---转

    http://www.iteye.com/topic/774673 羞愧呀,不知道多少人干过,我也干过,面壁去! 这帖是用来回复高级语言虚拟机圈子里的一个问题,一道Java笔试题的. 本来因为见得太多 ...

  5. 再看Ajax

    再回顾Ajax相关的内容,再次梳理学习还是很有必要的,尤其是实际的开发中,ajax更是必不可少,仔细学习以便避免不必要的错误. 文章导读: --1.使用XMLHttpRequest---------- ...

  6. Android菜鸟的成长笔记(17)—— 再看Android中的Unbounded Service

    原文:Android菜鸟的成长笔记(17)-- 再看Android中的Unbounded Service 前面已经写过关于startService(Unbounded Service)的一篇文章:&l ...

  7. 再看Java之温故知新(体系篇)

    一 数据类型 1.1 8种基本数据类型 1.2 引用数据类型 1.3 java内存机制 1.3.1 寄存器 1.3.2 栈 1.3.3 堆 1.3.4. 静态区/方法区 1.3.5. 运行时常量池(R ...

  8. mysql索引设计的注意事项(大量示例,收藏再看)

    mysql索引设计的注意事项(大量示例,收藏再看) 目录 一.索引的重要性 二.执行计划上的重要关注点 (1).全表扫描,检索行数 (2).key,using index(覆盖索引) (3).通过ke ...

  9. 再看ftp上传文件

    前言 去年在项目中用到ftp上传文件,用FtpWebRequest和FtpWebResponse封装一个帮助类,这个在网上能找到很多,前台使用Uploadify控件,然后在服务器上搭建Ftp服务器,在 ...

随机推荐

  1. Vue源码分析之数据驱动

    响应式特点 数据响应式 修改数据时,视图自动更新,避免繁琐Dom操作,提高开发效率 双向绑定 数据改变,视图随之改变.视图改变,数据随之改变 数据驱动 开发时仅需要关注数据本身,不需要关心数据如何渲染 ...

  2. secureCRT中sftp的使用

    securecrt 按下ALT+P就开启新的会话 进行ftp操作.输入:help命令,显示该FTP提供所有的命令pwd: 查询linux主机所在目录(也就是远程主机目录)lpwd: 查询本地目录(一般 ...

  3. Fiddler添加显示ip和响应时间

    1. 打开Fiddler,在菜单Rules 栏里点击Customize Rules…或者使用快捷键CTRL+R打开Fiddler ScriptEditor 图 1 Customize Rules 2. ...

  4. go语言之文件操作

    一: 相关的API 1func Create(name string) (file *File, err Error) 根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666 2 func ...

  5. php高效读取和写入

    /** * 删除非空目录里面所有文件和子目录 * @param string $dir * @return boolean */ function fn_rmdir($dir) { //先删除目录下的 ...

  6. sublime Text 3安装 Sublime Package Control(这个可以用于安装各种插件)时显示默认安装的c盘内存不够的解决方案

    首先先关闭st3 之后在安装的路径下创建Data文件夹,然后打开st3(sublime Text 3简写)CTRL+`打开命令行输入以下内容,直接回车,等待下载完成就可以了import urllib. ...

  7. webpack打包初始入门教程

    Webpack 是一个前端资源加载/打包工具.它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源. 从图中我们可以看出,Webpack 可以将多种静态资源 js.css ...

  8. 我对Flutter的第一次失望

    老孟导读:此文翻译自:https://medium.com/@suragch/my-first-disappointment-with-flutter-5f6967ba78bf 我喜欢Flutter. ...

  9. LuaProfiler

    Lua Profiler机制的源码解析 https://www.jianshu.com/p/f6606b27e9de

  10. 在Windows和MacOS下编译Lua

    官方说明: http://www.lua.org/manual/5.3/readme.html 在Windows下编译Lua动态链接库的注意事项: 1. 创建一个空的DLL项目: 2. 将src文件夹 ...