有无数的问题和答案Comparable
,Comparator
但似乎没有一个解决这个问题。
假设我有这个方法compare
,它接受 a 和 b 的任何Comparable
实现并返回比较 -1、0 或 1。
static <U,T extends Comparable<U>> int compare(T a, U b) {
return a.compareTo(b);
}
Run Code Online (Sandbox Code Playgroud)
与任何Comparable
东西一起工作都很好而且花花公子。整个企业的每个项目都采用该方法。
jshell> compare(1, 2);
$1 ==> -1
jshell> compare("id", "hi");
$2 ==> 1
Run Code Online (Sandbox Code Playgroud)
然后数据突然发生变化,我们开始遇到问题。
jshell> compare(null, "hi");
| Exception java.lang.NullPointerException: Cannot invoke "java.lang.Comparable.compareTo(Object)" because "<parameter1>" is null
| at compare (#1:2)
| at (#2:1)
jshell> compare(1, null);
| Exception java.lang.NullPointerException: Cannot read field "value" because "anotherInteger" is null
| at Integer.compareTo (Integer.java:1473)
| at Integer.compareTo (Integer.java:71)
| at compare (#1:2)
| at (#3:1)
Run Code Online (Sandbox Code Playgroud)
寻找其他 SO 问题的答案,他们都会重复文档所说的内容:
请注意,null 不是任何类的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也应该抛出 NullPointerException。
现在这是根本不能接受的!我们有Comparator 类nullsFirst
,其中包含这样的方法nullsLast
,那么我们如何在不更改方法名称和签名的情况下解决这个问题。我们希望空值小于非空值,并且当两者都为空时,应将它们视为相等。此外,客户非常挑剔,不会接受任何 if equals null 或if (a == null)
比较的胡闹。
我们如何更改流行的比较方法以仍然接受任何两个(Comparable
包括空值)并产生以下返回。
jshell> compare(1, 2);
$5 ==> -1
jshell> compare("id", "hi");
$6 ==> 1
jshell> compare(null, "hi");
$7 ==> -1
jshell> compare(1, null);
$8 ==> 1
jshell> compare(null, null);
$9 ==> 0
Run Code Online (Sandbox Code Playgroud)
你需要修改你的compare
方法。改变这个:
static <U,T extends Comparable<U>> int compare(T a, U b) {
return a.compareTo(b);
}
Run Code Online (Sandbox Code Playgroud)
对此:
static <U,T extends Comparable<U>> int compare(T a, U b) {
if (a == null) {
return (b == null) ? 0 : -1;
} else if (b == null) {
return +1;
} else {
return a.compareTo(b);
}
}
Run Code Online (Sandbox Code Playgroud)
客户端特别不希望进行任何 if equals null 或 if (a == null) 比较。为什么我们不能简单地使用它,
Comparator.nullsFirst
因为它已经达到了我们想要的效果?
因为它不起作用。
(更正:实际上,@AndreyB.Panfilov对现已删除的答案发表了评论:
return Comparator.nullsFirst(Comparator.<T>naturalOrder()).compare(a, b);
Run Code Online (Sandbox Code Playgroud)
但这并不影响我接下来要说的内容。)
有时客户的要求太愚蠢了,你不得不推迟。您需要教育客户。严重地。尝试符合他们的最大利益。
但是,如果你确实有一个客户毫无理由地坚持认为null
文字是撒旦的产物(或其他东西)......你可以null
使用Objects.isNull
(javadoc)来实现检查。
归档时间: |
|
查看次数: |
794 次 |
最近记录: |