2

我目前正在从 java 切换到 kotlin,并且不断弹出的声明的优点之一是 kotlin 是 Null 安全的,默认情况下不能为变量或对象分配 null 值,但有一些方法可以分配一个空值。但是我不确定为什么这是有益的,Java 不安全会出现什么问题?

到目前为止,在线搜索只得到了关于什么是空安全性的描述,而不是实现它的原因。提前致谢。

4

2 回答 2

5

这基本上是一个打字问题。

你不妨问这个完全类似的问题:

“我目前正在从 javascript 切换到 java 的过程中,不断出现的优势之一是 java 是类型化的,不能为变量或对象分配一个你没想到的值。但是我不确定为什么这是有益的,因为 Javascript 不是类型安全会出现什么问题?”

假设我写了这个方法。很简单:

public boolean areBanksOpen(LocalDate someDate) {
  ...
}

这种方法检查有关官方国定假日之类的书籍。在您的脑海中,您应该创建这样的概念,即代码的某些部分的作者与代码的其他部分的作者不同。即使对于只有一个人从事的项目:然后是您,三年前编写一些代码,而不是您今天使用该代码。你不记得(或者不应该记住)你当时写的代码的每一个角落和缝隙。

鉴于不是同一个人,沟通非常重要。您需要从该方法的作者与areBanksOpen该方法的用户进行沟通:它叫什么,它做什么,你如何使用它?是的,你当然可以写一个巨大的教程,但沟通比这复杂一点;如果你 95% 的编程时间都花在了浏览器上阅读教程上,那就不好了。快速提醒,以及来自编辑器环境的“训练轮”,可以检测你犯的错误,这些都是不错的选择。

在java中,打字就是这样做的。在java中,你不能写areBanksOpen("10-12-2021"). 您的编辑器会立即告诉您这是行不通的,您必须指定一个LocalDate实例,而不是String. 在 javascript 中,直到你运行它你才知道。

虚无也是一样。IDE 或阅读 javadoc 的人无法确定该areBanksOpen方法是否接受 null。我可以打电话areBanksOpen(null)吗?返回类型也一样:给定一个方法String getStudentName(StudentId studentId)null甚至可以返回吗?

从这个意义上说,java 中的所有类型实际上都是That | Null- 就像该getStudentName方法返回“字符串或 null”一样,这就是签名的含义,即使文档调用:如果studentId未找到,此方法会引发一些异常,并且所有学生都有一个 ID(因此暗示:不,此方法永远不会返回 null)。方法签名不传达该信息,只有文档可以传达。完全类似于 javascript 中的方法:

/** Pass a date object, returns a boolean whether banks are open */
function areBanksOpen(date) { .. }

in javascript 解释了它在文档中的工作原理,但签名本身不提供此信息,这意味着 [A] 编辑器不能成为第二双眼睛,因为编辑器不阅读文档但他们可以理解签名,并且[B] 您不会从自动完成框等中的快速查找中受益。

就是优势所在:在 kotlin 中,您确实知道,您的编辑器也知道

然而,告诉你这件事的人被误导了。Java也有这个,它被称为nullity annotations。在 java 中,你可以执行以下操作:

public boolean areBanksOpen(@NonNull LocalDate when) {}

然后 IDE 将对任何调用尝试areBanksOpen(null)areBanksOpen(someVar)简单的代码分析显示someVar可能包含null值的地方进行 insta-redline。这不是切换到 kotlin 的理由。

于 2021-12-20T13:21:22.190 回答
1

没有零安全...

  1. 很容易忘记类中的成员引用可能为空。如果您使用您认为是对象引用但实际上为 null 的内容,则会收到 NullPointerException。

  2. 没有编译器强制的方法来声明它只能处理非空参数。作者可以用一些注释对其进行标记或在方法的文档中对其进行注释,但仍可能传递空值并导致 NullPointerException 或作者选择的其他异常。

  3. 一个方法没有编译器强制的方式来声明它可能返回一个空值。作者可以在文档中提及或添加一些注释,但如果您没有注意到这些或忘记了这些,您可能会尝试使用 null 返回值作为对象引用并导致 NullPointerException。

  4. 如果曾经从不返回 null 的方法开始有时返回 null,则曾经有效的代码可能会停止工作并开始导致 NullPointerExceptions。由于它不是由编译器强制执行的,因此您会在运行时收到异常,而不是收到编译器错误,以便您可以修复它。

于 2021-12-20T14:11:57.493 回答