84669 Lernen von Personen
152542 Lernen von Personen
20005 Lernen von Personen
5487 Lernen von Personen
7821 Lernen von Personen
359900 Lernen von Personen
3350 Lernen von Personen
180660 Lernen von Personen
48569 Lernen von Personen
18603 Lernen von Personen
40936 Lernen von Personen
1549 Lernen von Personen
1183 Lernen von Personen
32909 Lernen von Personen
是不是定义字符串如果不使用new来初始化的话相同的字符串会被定义成一个引用
闭关修行中......
JVM对于String的存储有一点特殊的地方在于有一块String常量池。这个常量池里面存着对String对象的引用。
String
String常量池
比如,String s = "abc"会先去String常量池中查找有没有已经存在的引用,如果没有,声明的abc会直接生成一个String对象,并且会在String常量池中存入一个引用指向这个String对象。
String s = "abc"
之后直接声明的字符串同样也会遵循上面的步骤,所以第二次String s2 = "abc"从String常量池中找到了一个引用指向第一次声明的字符串对象。
String s2 = "abc"
而new String("abc")这样会直接在堆中创建新的对象,不会进入String常量池。要把这样的对象引用放入常量池中就涉及另一个String类的方法intern(),这个方法就是返回一个String对象的常量池引用。如果这个对象不在常量池中,就会把这个String对象放入常量池中并返回对应的对象引用。
new String("abc")
intern()
题主第一个截图的方法str2.intern() == str3.intern()这样使用也会返回true,调用intern()返回的String常量池引用是同一个。
str2.intern() == str3.intern()
true
Java中所有非内置数据类型都是引用。
String s = new String("xx");这种方式会创建一块内存空间,并使引用s指向它。
String s = "xx";这种方式会使引用s指向一块共享的空间。
使用new的方式创建时str2和str3指向的不同的内存空间,故str2和str3是不相等的。
直接使用字符串赋值时str2和str3指向是的相同的内存空间,故str2和str3是相等的。
可以使用str2.equals(str3)来比较字符串的内容。
一个是在常量池中存储,一个是在堆中new出新对象
帮助你理解这个过程。java中有几个点你可以记住下1.所有的字符串都会在常量池生成,对应的是CONSTANT_String_info,不可变。2.普通的对象几乎都是在堆中生成(当然也有一些比较特殊的比如Class类的对象可能在方法区生成,这个看不同的虚拟机实现,虚拟机规范并没有强制)3.==这个判定的时候,对于引用类型,说到底都是比对内存地址。
好了,有了上述的观念。第一个问题中,String s1 = new String("aaa"); 当你new一个对象,jvm就会在堆上帮你开辟一个对象空间,而s1是存在你的本地变量表的,s1指向这个对象空间(可以暂时理解为s1存着对象空间的地址)。所以你new了两个,是两个不同的对象空间。==判断当然不同啦,因为,s1和s2指向不同的空间。
第二个问题,上述第一点,每个字符串都只会在常量池中存在一份,所以str2指向这个常量池字符串的地址,str3也是指向这个常量池字符串的地址。==判断自然是相同的。
JVM对于
String
的存储有一点特殊的地方在于有一块String常量池
。这个常量池里面存着对String对象的引用。
比如,
String s = "abc"
会先去String常量池
中查找有没有已经存在的引用,如果没有,声明的abc会直接生成一个String对象,并且会在String常量池
中存入一个引用指向这个String对象。之后直接声明的字符串同样也会遵循上面的步骤,所以第二次
String s2 = "abc"
从String常量池
中找到了一个引用指向第一次声明的字符串对象。而
new String("abc")
这样会直接在堆中创建新的对象,不会进入String常量池
。要把这样的对象引用放入常量池中就涉及另一个String类的方法intern()
,这个方法就是返回一个String对象的常量池引用。如果这个对象不在常量池中,就会把这个String对象放入常量池中并返回对应的对象引用。题主第一个截图的方法
str2.intern() == str3.intern()
这样使用也会返回true
,调用intern()
返回的String常量池
引用是同一个。Java中所有非内置数据类型都是引用。
String s = new String("xx");这种方式会创建一块内存空间,并使引用s指向它。
String s = "xx";这种方式会使引用s指向一块共享的空间。
使用new的方式创建时str2和str3指向的不同的内存空间,故str2和str3是不相等的。
直接使用字符串赋值时str2和str3指向是的相同的内存空间,故str2和str3是相等的。
可以使用str2.equals(str3)来比较字符串的内容。
一个是在常量池中存储,一个是在堆中new出新对象
帮助你理解这个过程。java中有几个点你可以记住下
1.所有的字符串都会在常量池生成,对应的是CONSTANT_String_info,不可变。
2.普通的对象几乎都是在堆中生成(当然也有一些比较特殊的比如Class类的对象可能在方法区生成,这个看不同的虚拟机实现,虚拟机规范并没有强制)
3.==这个判定的时候,对于引用类型,说到底都是比对内存地址。
好了,有了上述的观念。第一个问题中,
String s1 = new String("aaa"); 当你new一个对象,jvm就会在堆上帮你开辟一个对象空间,而s1是存在你的本地变量表的,s1指向这个对象空间(可以暂时理解为s1存着对象空间的地址)。所以你new了两个,是两个不同的对象空间。==判断当然不同啦,因为,s1和s2指向不同的空间。
第二个问题,上述第一点,每个字符串都只会在常量池中存在一份,所以str2指向这个常量池字符串的地址,str3也是指向这个常量池字符串的地址。==判断自然是相同的。