Algorithms I - Module 0: Java Review

Value Equality v.s. Reference Equality

TypeReference Equality== 比较Value Equalityequals() 比较
PrimitivevalueN/A
Referenceaddresscontents

基本类型不需要区分值和引用,因为它们本身就是值,而引用类型存储的是对象的地址,所以需要明确区分两者的比较方式。

字符串比较

Java 的字符串池(String Pool)

在 Java 中,字符串池(String Pool)是 JVM 维护的一块特殊内存区域,用于存储字符串字面量(即直接写在代码中的 "This is a string.")。如果一个字符串字面量已经存在于池中,那么新的相同字面量不会创建新的对象,而是直接复用已有的对象。

1
2
String literal = "This is a string.";
String anotherLiteral = "This is a string.";

System.out.println(literal == anotherLiteral); // true

这里 literalanotherLiteral 直接指向同一个字符串池中的 "This is a string.",所以 == 比较返回 true

new String() 总是创建新的对象

当使用 new String("This is a string.") 时,JVM 无论字符串池中是否有该字符串,都会创建一个新的 String 对象

1
2
String object = new String("This is a string.");
String literal = "This is a string.";

System.out.println(literal == object); // false

这里 literal 存储的是字符串池中的对象,而 objectnew 关键字创建的一个新对象,它存储在堆(Heap) 中,而不是字符串池中。因此 literal == object 返回 false

equals() 用于内容比较

如果要比较 String 的内容,应该使用 equals() 方法:

1
2
3
4
String object = new String("This is a string.");
String literal = "This is a string.";

System.out.println(object.equals(literal)); // true

equals() 方法会逐个比较字符串的字符内容,而 == 只是比较对象的引用地址。


如何让 new String() 的对象和池中的字符串相等

如果你想让 new String() 创建的对象和池中的字符串共享引用,可以使用 intern() 方法:

1
2
3
4
5
String object = new String("This is a string.");
String interned = object.intern();
String literal = "This is a string.";

System.out.println(literal == interned); // true

intern() 方法会检查字符串池中是否已经存在该字符串,如果存在,就返回池中的对象;否则,它会把该字符串加入字符串池,并返回该对象的引用。

总结

1
2
String object = new String("This is a string.");
String literal = "This is a string.";
比较表达式 结果 原因
literal == object false literal 是字符串池中的对象,objectnew 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 objectnew 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
2
3
4
5
6
7
8
9
public static void main(String[] args) {     
int count = 0;
helper(count);
System.out.println(count);
}

public static void helper(int x) {
x = x + 1;
}
  • count 是基本类型,传给 helper 后,x 拿到的是一个 复制的值
  • helper 中对 x 做的任何修改,不会影响 main() 里的 count
  • 所以输出仍是 0

创建了新对象

1
2
3
4
5
6
7
public static void main(String[] args) {     
Container count = new Container(0);
helper(count);
System.out.println(count.getItem());
} public static void helper(Container x) {
x = new Container(x.getItem() + 1);
}
  • count 是一个引用变量,指向某个对象。
  • 传给 helper 后,x 拿到的是这个“引用”的副本,也指向原来的对象。
  • 但你在 helper新建了一个对象,并让 x 指向它,这只是改了 x 的指向,并没有改 count 的指向
  • 所以 main() 里的 count 还是原来的对象,item0

修改了对象内容

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
Container count = new Container(0);
helper(count);
System.out.println(count.getItem());
}

public static void helper(Container x) {
x.setItem(x.getItem() + 1);
}
  • 没有创建新对象,而是通过引用修改了原对象的内容
  • 所以 count.getItem() 的值真的变成了 1。

Algorithms I - Module 0: Java Review
https://hexwhat.top/2025/04/06/cs1332-1-0/
作者
Wynn
发布于
2025年4月6日
许可协议