【发布时间】:2021-07-29 06:21:56
【问题描述】:
关于 Dart 中的 null 安全性,我无法完全理解一件事,那就是如何安全地从 Map<String,dynamic> 检索值(我已阅读 Dart 文档中的 FAQ)。
基本上DartPad with null-safty enabled中的以下代码是有效的:
void main() {
int i;
Map<String, dynamic> map = {"key": 1};
i = map["key"];
print(i);
}
我不明白。为什么我可以将map["key"] 分配给i 而编译器不会对我大喊大叫?来自docs:
默认情况下代码应该是安全的。如果你写了新的 Dart 代码并且没有 使用任何显式不安全的功能,它从不抛出空引用 运行时出错。
但正是这种情况正在发生。如果在上面的代码中,key 不在 map 中,或者包含一些随机类型,程序将在运行时崩溃,我认为这是 null 安全不应该发生的。
我对此特别感兴趣,因为我正在编写一个 Flutter 应用程序并且不了解如何正确反序列化我从数据库中获取的 JSON 数据(try..catch?特殊语法,如??=?)。即使我没有启用“不可为空”语言功能(我什至不能在没有收到警告的情况下编写int? val),编译器似乎并不介意我将可空值分配给不可空变量,如果它们为空,会很高兴在运行时崩溃。
基本上,我的问题不仅涉及空安全性,还涉及一般的类型系统,因为据我了解,不可能将 dynamic 值分配给 int 变量,但显然这是可行的与Map。任何解释都非常感谢!
【问题讨论】:
-
您没有分析错误,因为您的
Map被声明为具有dynamic值。因此它的operator []返回dynamic?,这与dynamic相同。dynamic类型禁用静态类型检查并完全依赖运行时检查。如果您想要正确的分析错误,请使用不可为空的值类型(例如Map<String, Object>)声明您的Map。 (可以说分析器应该认识到这种情况并坚持i应该仍然可以为空,但我不知道这是否真的可能。) -
此外,如果您在
pubspec.yaml文件中设置implicit-casts: false,您应该会收到关于dynamic到int分配的分析错误。 (我认为隐式转换是通过 null 安全性隐式禁用的,但dynamic的隐式转换可能有一些例外。) -
@jamesdlin 对于
implicit-casts: false,您错误地将pubspec.yaml写成了analysis_options.yaml。我认为它在 null-safe Dart 中不是false的原因可能是即使您确定 json 中的数据是非 null 的,您也必须使用int? i = map['i'];然后处理 @987654354 @。在某些情况下,您需要这种行为,而在某些情况下则不需要。顺便说一句,您的第一条评论应该放在答案框中。
标签: flutter dart types dart-null-safety