概要
在Java中,String str = “a”; 和 String str = new String(“a”); 这两行代码在功能上看似相同,但实际上它们在内存分配和引用行为上存在一些差异。
区别
(1)内存分配
- String str = “a”;:这行代码创建了一个字符串常量,并将它的引用赋值给变量str。这个字符串常量通常被存储在字符串常量池中(String Constant Pool),这是Java堆内存中的一个特殊区域,用于存储字符串字面量。如果之前已经存在相同的字符串字面量,则不会创建新的对象,而是直接引用已经存在的对象。
- String str = new String(“a”);:这行代码创建了一个新的String对象,并将其引用赋值给变量str。这个新的String对象在堆内存中分配内存,并且它的内容是字符串常量池中的"a"的一个拷贝。即使字符串常量池中已经存在"a",使用new操作符仍然会创建一个新的对象。
(2)引用相等性
- 对于String str1 = “a”; String str2 = “a”;,由于两个引用都指向字符串常量池中的同一个对象,因此str1 == str2将返回true(注意这里使用的是==操作符,它比较的是对象的引用地址)。
- 对于String str1 = new String(“a”); String str2 = new String(“a”);,由于每次使用new都会创建一个新的对象,因此str1 == str2将返回false。但是,由于它们的内容相同,所以str1.equals(str2)将返回true(这里使用的是equals方法,它比较的是对象的内容)。
(3)性能考虑
- 由于字符串常量池的存在,使用字符串字面量通常比使用new操作符创建字符串更高效,因为可以避免不必要的对象创建和内存分配。
- 然而,在需要修改字符串内容的情况下(例如,使用substring、concat等方法),即使原始字符串是常量,这些操作也会创建新的String对象。
总结
在面试中,你可以这样回答:
“在Java中,String str = “a”;和String str = new String(“a”);的主要区别在于内存分配和引用行为。使用字符串字面量时,字符串会被存储在字符串常量池中,并在可能的情况下复用已存在的对象。而使用new操作符则会创建一个新的String对象,并在堆内存中分配内存。因此,在比较两个字符串的引用时,如果它们都是使用字符串字面量创建的,则它们将引用同一个对象;而如果它们都是使用new操作符创建的,则它们将引用不同的对象,即使它们的内容相同。”