String类在Java开发中还是常见的,String类型的创建有两种方式。
String a = "ABC";
String b = new String("ABC");
然而这两种创建方式里面的学问大有不同。而且这个问题也是一个热门的面试话题。欢迎大家在评论区讨论。
第一种:使用字面量的方式直接创建。JVM首先在栈里面创建一个a的引用,然后检索字符串常量池(String pool,在jdk1.7之后存在堆内存里面,1.7之前存在于方法区里面)里面是否存在这个 “ABC" ,如果字符串常量池里面存在 ”ABC“ ,就会直接返回 ”ABC“ 的引用地址给a,如果不存在,那么就在字符常量池里面创建一个,然后再返回地址。
第二种:使用new的方式直接创建,创建字符串常量时,JVM会首先检查字符串常量池,如果 ”ABC“已经存在常量池中,那么不再在字符串常量池创建该字符串对象,而直接堆中创建该对象的副本,然后将堆中对象的地址赋值给引用b,如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中,然后在堆中创建该对象的副本,然后将堆中对象的地址赋值给引用b。
String b = new String("ABC");
个人见解:至少一个,最多两个。如果字符串常量池里面有”ABC",就只在堆里面创建一个,如果没有的话,则创建两个。
new String(“a”) + new String(“b”)
创建了多少个对象? 6个
①用于拼接的new StringBuilder()
②new String(“a”)
③字符串常量池中的"a"
④new String(“b”)
⑤字符串常量池中的"b"
⑥StringBuilder.toString()中的new String(“ab”),注意这里的String并没有在常量池中生成"ab"
总结:
String a = "ABC";
String b = new String("ABC");
很明显两者是不相等的,因为A是使用字面量的意思创建的,在常量池里面创建,b则是在堆里面创建,两者当然不一样。
String a = "A"+"B"+"C";
String c = "ABC";
String b = new String("ABC");
这里C是使用字面量的创建方式,虽然是A B C相加,但是Java有优化机制,最后的结果就是在常量池里面生成一个"ABC",然后C创建的时候就会去常量池里面寻找,发现常量池里面存在这一个字符串,然后就会返回这个字符串的引用地址。所以 A==C 是 true,但是和B作比较就是false的。
String a = "A"+"B";
String b = "C";
String c = a + b;
String d = new String("ABC");
String e = d;
这里a + b 确实是一个字符串"ABC",但是这是在堆内存里面的,并不是在常量池的。注意和上面的区别。但是我们看第四行,这是一个赋值语句,这个语句就是把d的引用地址赋值一份给e,所以d和e是指向同一个地址。
基本数据类型(8大类型 byte short char int long float double boolean):比较的就是值是否相等。
引用书类型(类,数组,String等等):比较的是地址值是否相等
String:可以查看源码,发现String类的equals方法被重写了,所以字符串的equals的方法就是判断字符串的内容是否相等。
其他的类:自己写的,如果没有重写equals方法,类就会继承并使用object类的equals比较方法,查看源码可以发现还是用==做比较。所以比较的还是内存中的地址值。
评论 (0)