Java中String直接赋值和使用new的区别:

String str2 = new String(“ABC”);
String str1 = “ABC”;

String str1 = “ABC”;可能创建一个或者不创建对象。

从JDK1.7版本之后,java String池设置在堆中;

如果”ABC”这个字符串在java String池里不存在,会在java String池里创建一个String对象(“ABC”),然后str1指向这个内存地址。

String str2 = “ABC”;如果"ABC"这个字符串在java string池中存在,则不创建对象, str2指向字符串池中的"ABC"内存的地址(相当于两个栈,str1,str2,都指向相同的那个堆(“ABC”)),Java中称为“字符串驻留”,所有的字符串常量都会在编译之后自动地驻留。

String str2 = new String(“ABC”);至少创建一个对象,也可能两个。因为用到new关键字,肯定会在heap(堆)中创建一个str2的String对象,它的value是“ABC”。同时如果这个字符串在java String池里不存在,会在java池里创建这个String对象“ABC”。

在JVM里,考虑到垃圾回收(Garbage Collection)的方便,将heap(堆)划分为三部分:young generation(新生代)、tenured generation (old generation)(旧生代)、permanent generation(永生代)。

字符串为了解决字符串重复问题,生命周期长,存于pergmen中。

JVM中,相应的类被加载运行后,常量池对应的映射到JVM运行时的常量池中。

考虑下面的问题:

String str1 = new String(“ABC”);
String str2 = new String(“ABC”);

str1 == str2的值是true还是false呢?false

String str3 = “ABC”;
String str4 = “ABC”;
String str5 = “AB” + “C”;
str3 == str4 //true
str3 == str5 // true

String a = “ABC”;
String b = “AB”;
String c = b + “C”;
System.out.println( a == c );//false

a、b在编译时就已经被确定了,而c是引用变量,不会在编译时就被确定。

应用的情况:建议在平时的使用中,尽量使用String = “abcd”;这种方式来创建字符串,而不是String = new String(“abcd”);这种形式,因为使用new构造器创建字符串对象一定会开辟一个新的heap空间,而双引号则是采用了String interning(字符串驻留)进行了优化,效率比构造器高。

Java中字符串(String)引用类型的存储和赋值原理:

栈:由JVM分配区域,用于保存线程执行的动作和数据引用。栈是一个运行的单位,Java中一个线程就会相应有一个线程栈与之对应。
堆:由JVM分配的,用于存储对象等数据的区域。
常量池:在编译的阶段,在堆中分配出来的一块存储区域,用于存储显式的String,float或者integer.例如String str=“abc”; abc这个字符串是显式声明,所以存储在常量池。
观察下面的源码:
public class StringTest{

@Test
public void testTheSameReference1(){
    String str1="abc";
    String str2="abc";
    String str3="ab"+"c";
    String str4=new String(str2);
    
    //str1和str2引用自常量池里的同一个string对象
    str1==str2
    //str3通过编译优化,与str1引用自同一个对象
    str1==str3
    //str4因为是在堆中重新分配的另一个对象,所以它的引用与str1不同
    str1!=str4
} 

}
第一个断言很好理解,因为在编译的时候,“abc"被存储在常量池中,str1和str2的引用都是指向常量池中的"abc”。所以str1和str2引用是相同的。
第二个断言是由于编译器做了优化,编译器会先把字符串拼接,再在常量池中查找这个字符串是否存在,如果存在,则让变量直接引用该字符串。所以str1和str3引用也是相同的。
str4的对象不是显式赋值的,编译器会在堆中重新分配一个区域来存储它的对象数据。所以str1和str4的引用是不一样的。

你可能感兴趣的:(JAVA)