Algorithms I - Module 0: Java Review
Value Equality v.s. Reference Equality
| Type | Reference Equality== 比较 | Value Equalityequals() 比较 |
|---|---|---|
| Primitive | value | N/A |
| Reference | address | contents |
基本类型不需要区分值和引用,因为它们本身就是值,而引用类型存储的是对象的地址,所以需要明确区分两者的比较方式。
字符串比较
Java 的字符串池(String Pool)
在 Java 中,字符串池(String Pool)是 JVM 维护的一块特殊内存区域,用于存储字符串字面量(即直接写在代码中的 "This is a string.")。如果一个字符串字面量已经存在于池中,那么新的相同字面量不会创建新的对象,而是直接复用已有的对象。
1 | |
System.out.println(literal == anotherLiteral); // true
这里 literal 和 anotherLiteral 直接指向同一个字符串池中的 "This is a string.",所以 == 比较返回 true。
new String() 总是创建新的对象
当使用 new String("This is a string.") 时,JVM 无论字符串池中是否有该字符串,都会创建一个新的 String 对象。
1 | |
System.out.println(literal == object); // false
这里 literal 存储的是字符串池中的对象,而 object 是 new 关键字创建的一个新对象,它存储在堆(Heap) 中,而不是字符串池中。因此 literal == object 返回 false。
equals() 用于内容比较
如果要比较 String 的内容,应该使用 equals() 方法:
1 | |
equals() 方法会逐个比较字符串的字符内容,而 == 只是比较对象的引用地址。
如何让 new String() 的对象和池中的字符串相等
如果你想让 new String() 创建的对象和池中的字符串共享引用,可以使用 intern() 方法:
1 | |
intern() 方法会检查字符串池中是否已经存在该字符串,如果存在,就返回池中的对象;否则,它会把该字符串加入字符串池,并返回该对象的引用。
总结
1 | |
| 比较表达式 | 结果 | 原因 |
|---|---|---|
literal == object |
false |
literal 是字符串池中的对象,object 是 new String() 创建的对象 |
literal == "This is a string." |
true |
"This is a string." 在编译时已存入字符串池,literal 也是该池的引用 |
"This is a string." == "This is a string." |
true |
直接使用的字面量,指向同一个字符串池中的对象 |
object == "This is a string." |
false |
object 是 new String() 创建的,存于堆中,而 "This is a string." 存于字符串池 |
object == new String("This is a string.") |
false |
new String() 每次都会创建新的对象,两个对象的引用不同 |
Pass by Value/Reference
🔧总结
✅ Java 是 Pass by Value(按值传递)
但这“值”可以是两种类型:
- 基本类型(primitive):传的是实际值的副本。
- 引用类型(object):传的是引用的副本(也就是说,这个引用是指向对象的地址的一个拷贝)。
基本类型(int)
1 | |
count是基本类型,传给helper后,x拿到的是一个 复制的值。- 在
helper中对x做的任何修改,不会影响main()里的count。 - 所以输出仍是
0。
创建了新对象
1 | |
count是一个引用变量,指向某个对象。- 传给
helper后,x拿到的是这个“引用”的副本,也指向原来的对象。 - 但你在
helper中 新建了一个对象,并让 x 指向它,这只是改了x的指向,并没有改 count 的指向。 - 所以
main()里的count还是原来的对象,item是0。
修改了对象内容
1 | |
- 没有创建新对象,而是通过引用修改了原对象的内容。
- 所以
count.getItem()的值真的变成了 1。