【问题标题】:Dart: Null-safety and retrieving values from mapsDart:空安全和从地图中检索值
【发布时间】: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&lt;String, Object&gt;)声明您的 Map。 (可以说分析器应该认识到这种情况并坚持 i 应该仍然可以为空,但我不知道这是否真的可能。)
  • 此外,如果您在pubspec.yaml 文件中设置implicit-casts: false,您应该会收到关于dynamicint 分配的分析错误。 (我认为隐式转换是通过 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


【解决方案1】:

动态变量可以包含任何数据类型,当您不知道可能返回的具体数据类型时使用“动态”关键字。

以及你在这里实际做的事情:

i = map["key"];

正在将“动态”变量分配给“int”变量,并且由于在这种情况下是动态的,因此 Map 的键/值对中的值是一个整数,它与变量“i”的数据类型“int”匹配不会因为在运行时而不是编译时进行类型推断而崩溃。如果“动态”变量是一个字符串,它会因为类型不匹配而在运行时崩溃。希望这是解释性的。

【讨论】:

    猜你喜欢
    • 2021-03-21
    • 2021-06-16
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 2022-01-11
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多