Yih*_*Gao 15 language-design dart kotlin kotlin-null-safety dart-null-safety
这段 Dart 官方视频指出,Dart 所谓的“声音空安全”比 Kotlin 的空安全设计要好,因为它可以根据变量是否被声明为可空来优化代码,其他语言(我假设这是指包括 Kotlin 在内的语言) ) 必须进行运行时检查以确保空值安全。
那么,Dart 做了哪些额外的优化?
它如何与不支持空安全的遗留代码库互操作,同时确保空安全?
cre*_*not 16
那么,Dart 还做了哪些额外的优化呢?
Dart 中健全的null 安全性的好处是编译器可以使用不可为 null 的类型,从而消除 null 检查。因此,编译器将生成更少的指令(这会导致更小的二进制文件和更快的运行时间)。
取以下函数:
int getAge(Animal a) {
return a.age;
}
Run Code Online (Sandbox Code Playgroud)
这些是编译器在健全空安全之前生成的指令:
正如您所看到的,编译后的代码中有明确的检查 null 的指令。
这就是使用健全的 null 安全性编译的相同函数的样子:
现在,不再需要这些附加说明。
请注意,从 Dart 2.12 开始为示例函数生成的实际指令如下(还有进一步的优化):
请参阅Vijay Menon(Dart 工程主管)撰写的Dart 和声音类型的性能优势以供参考。
它如何与非空安全(在空安全之前编写)的遗留代码库进行互操作,同时确保空安全?
它不是。
嗯,这不是全部事实。如果您想将 Dart>=2.12.0与 Dart 2.12 之前编写的任何代码库(以及空安全之前的代码库)一起使用,则无法利用健全的空安全。但是,您可以通过传递禁用声音空安全性的编译器标志来与这些遗留代码库进行互操作。那就是--no-sound-null-safety(有关更多详细信息,请参阅我之前的回答)。
这意味着在与遗留代码库交互时,健全的空安全性的所有好处都会丢失。这也是为什么 Dart 团队鼓励所有包作者将他们的代码迁移到 null safety 的原因。
由于健全的 null 安全性,Kotlin 根本没有 Dart 通过未装箱值实现的额外编译器优化。
请记住,Kotlin 始终允许与 Java 进行互操作,而 Java 没有任何 null 安全的概念。我想这就是为什么 Kotlin 永远无法像与遗留代码库互操作的 Dart 代码那样拥有健全的null 安全性的原因。只要 Kotlin 代码是为具有 Java 互操作性的 JVM 编译的。
如果我们不关心编译后的代码而只关心开发者体验,那么 Kotlin 和 Dart 处理 null 安全性的方式是相同的。也就是说,两种语言默认情况下都是不可为空的(NNBD)。
这意味着在 Dart 2.12+ 或 Kotlin 中编写代码时,所有类型都被假定为不可为空,除非您明确将它们标记为可为空。
获得空指针异常的唯一方法是两种语言中的程序员错误,即!在 Dart 中使用 bang 运算符,在 Kotlin 中使用双 bang 运算符!!,即开发人员的非空断言。
请注意,当使用 null 断言时,必须在编译的代码中添加额外的运行时检查,以保持 Dart 的健全性。对于为 JVM 编译的 Kotlin 代码,这些检查始终存在,因为它一开始就不健全。
当使用 Kotlin 时与Java 代码互操作或使用 Dart 时与遗留代码互操作时,也可能会发生这种情况。
还有一些边缘情况,请参阅Kotlin 中的空安全性和了解 Dart 中的空安全性以供参考。
那么,Dart 还做了哪些额外的优化呢?
最基本的优化是,当对数值类型执行计算时,编译器可以(在内部)将它们视为非引用类型(未装箱值)的原始类型。
这是为什么?
因为它们不能为 null,因此没有必要将它们用作引用类型(装箱值)的数据。
这是为什么?
因为 null 在 Dart 中表示为 null 常量引用。
如果不需要引用这个常量,那么为什么不使用值类型而不是引用类型呢?至少在生成的代码中,可以在编译时对其进行优化。
这一切都得益于所谓的“强模式”。
强模式与不可空类型相结合,允许您在编译阶段就已经优化代码,这对于 AOT 等模式非常重要,因为 AOT 不允许在运行时优化代码,因为它在 RE 中(读取和执行)模式。
它如何与不支持空安全的遗留代码库进行互操作,同时确保空安全?
在我看来,你应该把这个问题作为一个单独的问题来问。
| 归档时间: |
|
| 查看次数: |
1348 次 |
| 最近记录: |