== 和 equal
- == 对比基本数据类型的值和引用对象的内存地址
- equal 判断两个对象是否相等,需要重写equals()方法,否则是判断两个对象是否指向一个对象。
equal
Object的equal方法,定义原型如下:
public boolean equals (Object x){
return this == x;
}
相等与同一
- 如果两个对象具有相同的类型以及相同的属性值,则称这两个对象相等。
- 如果两个引用对象指的是同一个对像,则称这两个变量同一。
深拷贝和浅拷贝
String的存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| 1. String str1 = "abc" System.out.println(str1 == "abc")
步骤: 1) 栈中开辟一块空间存放引用str1, 2) String池中开辟一块空间,存放String常量"abc", 3) 引用str1指向池中String常量"abc", 4) str1所指代的地址即常量"abc"所在地址,输出为true
2. String str2 = new String("abc"); System.out.println(str2 == "abc")
步骤: 1) 栈中开辟一块空间存放引用str2, 2) 堆中开辟一块空间存放一个新建的String对象"abc", 3) 引用str2指向堆中的新建的String对象"abc", 4) str2所指代的对象地址为堆中地址,而常量"abc"地址在池中,输出为false
3. String str3 = new String("abc"); System.out.println(str3 == str2);
步骤: 大专栏 地址和值s="number">1) 栈中开辟一块空间存放引用str3, 2) 堆中开辟一块新空间存放另外一个(不同于str2所指)新建的String对象, 3) 引用str3指向另外新建的那个String对象 4) str3和str2指向堆中不同的String对象,地址也不相同,输出为false
4. String str4 = "a" + "b" System.out.println(str4 == "ab")
步骤: 1) 栈中开辟一块空间存放引用str4, 2) 根据编译器合并已知量的优化功能,池中开辟一块空间,存放合并后的String常量"ab", 3) 引用str4指向池中常量"ab", 4) str4所指即池中常量"ab",输出为true
5. final String s = "a" String str5 = s + "b" System.out.println(str5 == "ab")
步骤: 同4
6. String s1 = "a" String s2 = "b" String str6 = s1 + s2 System.out.println(str6 == "ab")
步骤: 1) 栈中开辟一块中间存放引用s1,s1指向池中String常量"a", 2) 栈中开辟一块中间存放引用s2,s2指向池中String常量"b", 3) 栈中开辟一块中间存放引用str5, 4) s1 + s2通过StringBuilder的最后一步toString()方法还原一个新的String对象"ab",因此堆中开辟一块空间存放此对象, 5) 引用str6指向堆中(s1 + s2)所还原的新String对象, 6) str6指向的对象在堆中,而常量"ab"在池中,输出为false
7. String str7 = "abc".substring(0, 2)
步骤: 1) 栈中开辟一块空间存放引用str7, 2) substring()方法还原一个新的String对象"ab"(不同于str6所指),堆中开辟一块空间存放此对象, 3) 引用str7指向堆中的新String对象,
8. String str8 = "abc".toUpperCase()
步骤: 1) 栈中开辟一块空间存放引用str6, 2) toUpperCase()方法还原一个新的String对象"ABC",池中并未开辟新的空间存放String常量"ABC", 3) 引用str8指向堆中的新String对象
|