很久以前,有一个功能
public static Foo getFoo(Bar bar) {
return bar.getFoo();
}
人们只是无法同意如果bar为空会发生什么。
首先,有些人会声称违反功能意图的行为应该受到惩罚,但有一个检查的例外。
public static Foo getFoo(Bar bar) throws FooNotFoundException {
if (bar == null) throw new FooNotFoundException();
return bar.getFoo();
}
然后,将强制函数的调用方考虑此方案。它必须抓住异常或将其重新抛出。这将是如此有力,以至于它会惹恼人们,很快他们会争辩说这不应该是一个检查的异常,而是一个运行时异常,以使其不那么有力。
public static Foo getFoo(Bar bar) {
if (bar == null) throw new FooNotFoundException();
return bar.getFoo();
}
有些人会声称抛出异常是没有意义的,因为java无论如何都会抛出一个异常:Nullpointer异常。
那些担心意外异常的人,只会使他们的代码更加重构,并在函数开始时添加-checks,这只会返回null
。null
public static Foo getFoo(Bar bar) {
if (bar == null) return null;
return bar.getFoo();
}
很快,人们就会争论是否可以返回空列表,或者这些空列表是否真的也应该是值。“当然,你不想在每次迭代之前检查可空性,对吗?”对方会争辩。很快,他们将创建各种构造来完全避免可空性。null
public static Foo getFoo(Bar bar) {
if (bar == null) return Foo.Empty;
return bar.getFoo();
}
每种办法都会产生广泛的后果。这些后果将使人们难以将不同的方法结合起来。这些后果将导致编码规则,其中每个单独的规则将连接到下一个规则。他们相互支持的方式会给人一种印象,即每条规则都是无可争议的。最后,编码规则将变得像宗教一样,只有在整个规则集的范围内才有意义。
根据您选择的规则集,您将难以使用某些框架。最后,带有不受限制的例外的空名单宗教成为主导。这个宗教可以总结如下:
- 应避免返回值。
null
- 如果列表为空,则按原样返回。
- 如果迭代列表,则永远不必检查 null。
- 方法永远不应该抛出已检查的异常
- 已检查的异常应包装在运行时异常中。
- 字符串永远不应该是,相反,它们应该是。
null
""
显然,这个宗教变得如此强大,以至于它设法影响了框架和语言规范。
- 空列表的编译器优化
- 一个类
Optional
- 值类型
一些外部库和编辑器实际上会尝试通过提供注释( 和 ) 来重新统一不同的团队。IDE 将只为您标记所有冲突。一个简单但有效的解决方案。然而,JDK从未包含自己的库,或者,每个库都必须发布自己的库。@Null
@NotNull
@Null
@NotNull
考虑到所有这些,现在,Java中不太可能有猫王运算符。如果你想用java编写代码,你最好忘记.null
或者用Tony Hoare(null的发明者)的话来说:
我称之为我数十亿美元的错误。这是1965年零引用的发明。当时,我正在设计第一个面向对象语言(ALGOL W)引用的综合类型系统。我的目标是确保引用的所有使用都应该是绝对安全的,由编译器自动执行检查。但是我无法抗拒放入空引用的诱惑,仅仅因为它很容易实现。这导致了无数的错误,漏洞和系统崩溃,这些在过去四十年中可能造成了数十亿美元的痛苦和损害。
就个人而言,我认为这绝对没有意义,因为每个像样的编程语言都有一个null。有些甚至有多个来表示不同类型的空能力。毕竟,即使在数学中也有未定义的值。
无论如何,如果你没有猫王操作员,你仍然可以
Foo foo = bar == null ? null : bar.getFoo();
这完全符合java的精神。毕竟,在2021年,java是一种非常明确的语言。