- 创建String类的创建方式
-
String str = “one”;
这是第一种方式,创建的“one”保存在字符串常量池中(方法区),str这个引用保存的是字符串“one”的地址。
注意:字符串常量池,(为什么会在方法区呢,第一是可以节省内存,可以重复使用,不用new对象)顾名思义常量二字通常用 final修饰的,所以是只能一次赋值,所以也就有了字符串不可变(个人理解)。 -
String str1 = new String(“two”);
这是创建字符串的第二种方式,在堆中开辟了空间,通过str1这个引用来保存这个对象的地址,堆中对象保存了常量池中字符串的地址。所以用第二种方式来创建的字符串其实是创建了二个对象,一个是堆中对象,一个是常量池中的字符串对象。
大家可以对照下面的内存图片来理解。
- 深层理解
我们自定义一个引用类型数据user,里面有字符串name这个属性,栈中是user这个引用,保存了堆中对象的地址,堆中对象name属性保存的是方法区中字符串常量池中的String对象。所以说只要是看到字符串就一定是在常量池中拥有这个对象。
分析下这二个面试经常碰到的题目:
一、
String s1 = "hello";
String s2 = "hello";
System.out.println(s1==s2);//true
二、
String x = new String("xyz");
String y = new String("xyz");
System.out.println(x==y);//false
所以判断二个字符串不能用==,是用来比较内存地址,应该用equal方法来比较,当然equal方法底层也是,但String类重写了equal方法。所以我们自定义的类如果去比较时一定要记得重写equal方法。