Java类型安全的equals()

4
为什么Java中没有类型安全的equals()方法?我认为这可以在编译时捕获一些错误,而不是在运行时出现错误。以下是一个微不足道的例子:
class Person {
    Integer birthYear;
} 

class Car {
    Long releaseYear;
}

有一个方法可以接受一个人和一组汽车,并且假设列出与该人出生年份相同的所有汽车。可能会使用以下内容:

if (person.birthYear.equals(car.releaseYear)) {
...magic happens...
}

但是这并不会出现任何魔法。即使在创建代码时字段类型相同,其中任何一个字段稍后都可以更改,而不会在比较代码上产生编译错误。

避免这些问题的最佳实践是什么?


1
因为Java的类型系统不够丰富,无法实现这一点。 - SLaks
2
像FindBugs这样的工具可以警告在不能相等的类型上调用equals方法。 - fgb
这个也在这里讲解过了:http://rickyclarkson.blogspot.si/2006/12/making-equalsobject-type-safe.html - Emmanuel Touzery
1个回答

3

Java的 equals() 方法是这样设计的,它接受一个 Object 作为参数,因此你可以创建一个异构对象集合,并将它们相互进行比较以确定它们是否相等。

例如,你可能有一个任意对象的列表:

List<Object> lst = new ArrayList<>();
lst.add("abc");
lst.add(123);  // Integer
lst.add(456L);  // Long

那么equals()接收一个Object的事实意味着你可以实现以下内容:

void indexOf(List<Object> lst, Object target) {
    for (int i = 0; i < lst.size(); i++) {
        if (lst.get(i).equals(target))
            return i;
    }
    return -1;
}

针对您的问题,唯一保证"类型安全"的方法是定义一个新的方法名称,例如strictEquals(),并仅使用您的类型来实现参数,而不是使用Object类型。例如:

class Person {
    boolean strictEquals(Person other) { ... }
}

class Car {
    boolean strictEquals(Car other) { ... }
}

关于您使用IntegerLong作为字段,请不要这样做。相反,请使用原始类型intlong,并使用==运算符比较值。这有许多优点,例如更好的性能,没有NullPointerException,以及能够正确比较intlong(而Integer.equals(Long)将始终返回false,因为对象具有不同的类型,即使它们具有相同的数字值)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接