创建String对象的两种方式
- 直接赋值 String s1 = “dq”;
- 调用构造器 String s2 = new String(“dq”);
两种创建 String 对象的区别
方式一:先从常量池查看是否有"dq"数据空间,如果有,直接指向;如果没有则重新创建然后指向。s1最终指向的是常量池的空间地址
方式二:先在堆中创建空间,里面维护了value属性,指向常量池的dq空间。如果常量池没有"dq",重新创建,如果有,直接通过value指向。最终指向堆中的空间地址
小练习1
String a = "dq"; //a指向常量池
String b = new String("dq"); //b指向堆中对象
System.out.println(a == b); //F
System.out.println(a.equals(b)); //T
System.out.println(a == b.intern()); //T
System.out.println(b == b.intern()); //F
//当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),
// 则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
// intern()方法最终返回的是常量池的地址
小练习2
Person p1 = new Person();
p1.name = "hspedu";
Person p2 = new Person();
p2.name = "hspedu";
System.out.println(p1.name.equals(p2.name)); //T
System.out.println(p1.name == p2.name); //T 指向常量池中同一个地址
System.out.println(p1.name == "hspedu");; //T
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); //F
内存图
小练习3
String a = "hello";
String b = "abc";
String c = a + b;
//分析上面代码一共创建了几个对象
//1.先创建一个 StringBuilder sb = new StringBuilder()
//2. 执行 sb.append("hello")
//3. 执行 sb.append("abc")
//4. String c = sb.toString() toString()方法里 new String()
//最后c指向堆中的对象 (String) value[] -->(指向) 池中的 "helloabc"
//重要规则:String c1 = "ab" + "cd"; 常量相加,看的是常量池
//String c1 = a + b 变量相加,是在堆中
String d = "helloabc";
System.out.println(c == d); //F
String e = "hello" + "abc";
System.out.println(d == e); //T
小练习4
public class Exercise {
String str = new String("hsp");
final char[] ch = {'j','a','v','a'};
public void change(String str, char ch[]){
str = "java";
ch[0] = 'h';
}
public static void main(String[] args) {
Exercise ex = new Exercise();
ex.change(ex.str, ex.ch);
System.out.println(ex.str + "and"); //javaand
System.out.println(ex.ch); //hava
}
}