对于这个问题想必已经被无数面试者问烂了...而绝大多数人都会人云亦云的回答创建了2个。我们首先不来纠结这个答案到底是对是错。上代码:
/**
*
* @author Sonicery_D
*/
public class HelloString {
public static void main(String[] args){
String str = "ab";
String str1 = new String("abc");
String str2 = "abc";
System.out.println("str1==str2:"+(str1 == str2));//false
}
}
上面这段简单的代码按理来说应该是true才对,为什么会是false呢?
其实我们知道在JVM中有一个方法区的存在(Hotspot VM 用永久代来实现方法区),在方法区中就包括了一个常量池,当JVM遇到String str = “ab”;时它会首先在常量池中查找,看看是否有一个值为“ab”的对象,如果有就直接返回这个对象的引用;如果没有找到,就创建一个这个对象,然后把它放到常量池中,并返回它的引用。当然这个“ab”在编译期就放进了常量池,我们再待会儿会解释。
当JVM遇到String str1 = new String("abc");时,JVM会首先去常量池中查找是否存在值为“abc”的对象,如果找到不做任何处理,如果找不到就会先创建一个值为“abc”的对象然后把它放进常量池中,接着JVM又遇到了new,因此JVM又会在堆上创建一个存储“abc”的String对象,然后返回这个对象的引用。故而出现了上述代码中str1==str2 会是false的情况。
下面我们稍加看看它的字节码解释:
上面在main方法中的第一条指令是ldc,我们都知道ldc系列的命令是负责将数值常量或字符串常量值从常量池中推送到栈顶。由此可见String str = "ab";在编译期之后类加载时就将“ab”放入了常量池。
通new指令我们可以看到jvm在堆上创建了一个对象,并在随后又invokespecial了String的构造方法初始化对象。
对于回答会创建2个对象的,想必是:
String str = new String("abc");JVM首先在常量池中查找是否存在“abc”如果存在就啥也不做,如果不存在,就创建一个对象,并将它放入常量池,那么这就算了一个;当JVM遇到new时,又会在堆上创建一个String对象,并将其引用返回给str,这又是一个,加起来就是2个了。
但是如果是在String str3 = “abc”的前提下的String str = new String("abc"); 它还是会创建出两个对象吗?