掌握了关于Java内存的基础知识之后,我们就可以对这个面试题有更深入的理解了。
1. 案例代码
我们先编写面试题中涉及到的代码,如下所示:
代码很简单,就一行代码!那么问题来了,这行代码中共有几个对象呢?1个?2个?还是3个?要想弄明白到底有几个对象,壹哥 就给大家把这段代码的内存分区绘制了一下(本案例开发环境是基于JDK8)。
2. 内存分配(重点)
在 String s = new String("xyz"); 这行代码中,s是String类型的变量,不是对象!‘xyz’是字符串对象,new String("xyz")也是一个对象,那么它们几个的内存划分在JDK8的环境中,如下图所示:
那么根据上图,壹哥 就可以为各位给出本题的答案了,请仔细咯,重点来啦,内存分配过程如下:
当JVM在编译阶段加载读取到“xyz”的时候,首先会检查堆中的String常量池,也就是常量缓冲区,检查是否已经有了"xyz"常量对象,如果有,则不会再次创建"xyz"常量对象,并直接返回该字符串的引用地址;如果没有,则创建一个"xyz"常量对象,并为该对象分配一个内存地址002返回。
当JVM在运行阶段加载读取到new关键字的时候,JVM会在堆中为其创建一个对象,即new String(),并为其分配内存地址001,而堆中这个对象的内容是上面"xyz"常量对象的引用地址002,换句话说这个堆中存的就是常量池中"xyz"的引用地址002。
最后,s 是对当前堆中001号对象的一个地址引用,s本身不是一个对象,s只是一个String类型的变量而已!
3. 变量与对象
我们还需要弄明白一个问题,即变量与对象的区别。请问在 String s=new String("xyz");这行代码中,s是对象吗?
String类中有一种创建对象的特殊形式,就是可以使用 ""双引号 来创建对象,这种创建方式可以在一定程度上提高程序的运行速度,因为JVM会自动根据常量池中的数据存在实际情况来决定是否有必要创建新对象。在String s=new String("xyz")中,实际创建了2个String对象,一个是通过""双引号,在编译期创建的"xyz"常量对象;另一个是通过new String(),在运行期创建的。
但是 s 只是一个String类型的变量,不是对象,它只是对字符串对象的一个引用而已。所谓的对象,应该是需要在堆中分配了内存的类型才能叫做对象,s位于栈中,所以不是对象!
4. 问题答案(重点)
所以String s=new String("xyz")这行代码中究竟有几个对象,我们的答案要分两种情况来考虑:
●如果String常量池中已经有了"xyz"常量对象,那么答案就是只创建了一个对象,即new String();
●如果String常量池中没有创建"xyz"常量对象,则会创建两个对象,即一个"xyz"常量对象,一个new String()对象。
更多关于“Java培训”的问题,欢迎咨询千锋教育在线名师。千锋已有十余年的培训经验,课程大纲更科学更专业,有针对零基础的就业班,有针对想提升技术的好程序员班,高品质课程助力你实现java程序员梦想。