new String("yefeng")创建了几个对象
常见的面试题,下面代码中创建了几个对象
new String("yefeng");
为了明白这个问题,我们从底层原理来分析
String name = "yefeng"; // 在常量池中
String name1 = new String("yefeng"); // 在堆上
当我们如果直接赋值的话,字符串"yefeng"会呗存储在常量池中,只有一份,此时的赋值操作是创建0个或者1个对象。
如果常量池中已经存在了"yefeng", 那么不会再创建对象,直接引用赋值给name,如果常量池中没有"yefeng",那么创建一个对象,并引用赋值给name。
如果通过new String("yefeng");的形式会是怎么样的?
当JVM遇到上述代码,会检索常量池中是否存在'yefeng",如果不存在,则会先在常量池中创建一个这样的字符串。再通过new操作,会在堆中创建一个存储"yefeng"的String对象,对象然后在赋值给name1。此过程会创建2个对象。
当然,如果检索常量池时发现已经存在了对应的字符串,那么只会在堆内创建一个新的String对象,此过程只创建
了1个对象。在上述过程中检查常量池是否有相同Unicode的字符串常量时,使用的方法便是String中的intern()方法。
public native String intern();
上面的示意图我们可以看到在堆内创建的String对象的char value[]属性指向了常量池中的char value[]。还是上面
的示例,如果我们通过debug模式也能够看到String的char value[]的引用地址。
图中两个String对象的value值的引用均为{byte[6]@1181},也就是说,虽然是两个对象,但它们的value值均指向常量池中的同一个地址。当然,大家还可以拿一个复杂对象(Person)的字符串属性(name)相同时的debug结果进行比对,结果是一样的。