1. 引用等价性(Reference Equality)
引用等价性最简单粗暴,指两个引用是否指向同一个块内存空间。在Java中,可用使用`==`运算符来检查引用等价性。
String a = new String("hello");
String b = new String("hello");
String c = a;
System.out.println(a == b); // 输出 false,因为 a 和 b 引用的是不同的对象
System.out.println(a == c); // 输出 true,因为 a 和 c 引用的是同一个对象
2. 对象等价性(Object Equality)
对象等价性指两个对象的内容是否相同。在Java中,通常通过覆盖`equals`方法来实现对象等价性。
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || !(obj instanceof Person)) return false;
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
}
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Alice", 30);
Person p3 = p1;
System.out.println(p1.equals(p2)); // 输出 true,因为 p1 和 p2 的内容相同
System.out.println(p1.equals(p3)); // 输出 true,因为 p1 和 p3 是同一个对象
3. 观察等价性(Observational Equality)
观察等价性指从外部观察者的角度来看,两个对象的行为和状态是否相同,即它们是否在所有可能的观察中表现一致。这种等价性通常较难严格定义和实现。
如下所示,假设有两个具有相同行为的类,即使它们的内部实现不同,但从外部观察,它们表现一致:
class A {
public int getValue() {
return 42;
}
}
class B {
public int getValue() {
return 42;
}
}
A obj1 = new A();
B obj2 = new B();
System.out.println(obj1.getValue() == obj2.getValue()); // 输出 true,因为从外部看,两个对象的行为一致
4. 行为等价性(Behavioral Equality)
行为等价性指两个对象在所有可能的操作中都表现一致,不仅包括它们的状态,还包括它们对相同输入的反应。这通常意味着两个对象在所有可能的使用场景下的行为都相同。
interface Animal {
void makeSound();
}
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}
class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}
Animal dog = new Dog();
Animal cat = new Cat();
dog.makeSound(); // 输出 "Bark"
cat.makeSound(); // 输出 "Meow"
在这里,虽然`Dog`和`Cat`都是`Animal`的实现,它们在行为上是不同的,因为它们的`makeSound`方法有不同的输出,因此它们不具有行为等价性。
总结:
引用等价性: 使用`==`检查引用是否指向同一对象。
对象等价性: 使用`equals()`方法检查对象内容是否相同。
观察等价性: 对象从外部观察的行为和状态是否一致。
行为等价性: 对象在所有可能的操作中表现一致。