flutter - Dart 中的空安全性是什么?

标签 flutter dart

我听说过新的 Dart 空安全语言功能 (NNBD),目前是“ '不可空' 实验 ”。默认情况下,它应该引入 不可为空的

功能规范可以是 found here 和语言 GitHub issue here

它是如何工作的,我可以在哪里试用?

最佳答案

1.空安全/不可空(默认)
空安全/不可空(默认情况下),简称 NNBD,功能目前可以在nullsafety.dartpad.dev找到。
请记住,您可以阅读full spec herefull roadmap here。现在,声音零安全性也已成为officially announced for Dart

2.1.默认情况下不可为空是什么意思?

void main() {
  String word;
  print(word); // illegal

  word = 'Hello, ';
  print(word); // legal
}
如您所见,默认情况下不可为空的变量意味着通常声明为的每个变量都不能null。因此,在变量被赋值之前访问变量的任何操作都是非法的。
此外,也不允许将null分配给不可为空的变量:
void main() {
  String word;
  
  word = null; // forbidden
  world = 'World!'; // allowed
}
2.1.1.这对我有什么帮助?
如果变量不可为空,您可以确定它永远不会是null。因此,您永远不需要事先检查它。
int number = 4;

void main() {
  if (number == null) return; // redundant

  int sum = number + 2; // allowed because number is also non-nullable
}
2.1.2.记住
如果类中的实例字段不可为空,则它们必须初始化为:
class Foo {
  String word; // forbidden

  String sentence = 'Hello, World!'; // allowed
}
请参阅下面的late以修改此行为。
2.2.可空类型(?)
您可以通过将问号?附加到变量类型来使用可空类型:
class Foo {
  String word; // forbidden

  String? sentence; // allowed
}
可空变量在使用前不需要初始化。默认初始化为null:
void main() {
  String? word;
  
  print(word); // prints null
}
2.2.2. !!附加到任何变量e将抛出运行时错误如果e为空,否则将其转换为v非空值10491976 104567914”。
void main() {
  int? e = 5;
  int v = e!; // v is non-nullable; would throw an error if e were null

  String? word;
  print(word!); // throws runtime error if word is null

  print(null!); // throws runtime error
}
2.3. late关键字late可用于标记将在之后初始化为的变量,即不是在声明时而是在访问时。这也意味着我们可以拥有稍后初始化的不可为空的实例字段:
class ExampleState extends State {
  late final String word; // non-nullable

  @override
  void initState() {
    super.initState();

    // print(word) here would throw a runtime error
    word = 'Hello';
  }
}
在初始化之前访问word将引发运行时错误。
2.3.1. late final最终变量现在也可以标记为后期:
late final int x = heavyComputation();
这里heavyComputation只会在访问x时被调用。另外,你也可以声明一个没有初始化器的late final,这和只有一个late变量是一样的,但它只能被赋值一次。
late final int x;
// w/e
x = 5; // allowed
x = 6; // forbidden
请注意,所有具有初始化程序的顶级或静态变量现在都将被评估为 late,无论它们是否为 final
2.4. required以前是注释(@required),现在作为修饰符内置。它允许将任何命名参数(对于函数或类)标记为required,这使得它们不可为空:
void allowed({required String word}) => null;
这也意味着如果一个参数应该是不可为空的,它需要被标记为required或有一个默认值:
void allowed({String word = 'World'}) => null;

void forbidden({int x}) // compile-time error because x can be null (unassigned)
    =>
    null;
任何其他命名参数必须是可为空的:
void baz({int? x}) => null;
2.5. ?[]为索引运算符?[]添加了空感知[]运算符:
void main() {
  List<int>? list = [1, 2, 3];

  int? x = list?[0]; // 1
}
另见this article about the syntax decision
2.5.1. ?..级联运算符现在还有一个新的空感知运算符:?..
只有当接收者是而不是空时,它才会导致下面的级联操作被执行。因此,?..必须是级联序列中的第一个级联运算符:
void main() {
  Path? path;

  // Will not do anything if path is null.
  path
    ?..moveTo(3, 4)
    ..lineTo(4, 3);

  // This is a noop.
  (null as List)
    ?..add(4)
    ..add(2)
    ..add(0);
}

2.6. Never 下面的解释很烂。阅读"Top and bottom" from "Understanding null safety"是一个不错的选择。
为避免混淆:这不是开发人员必须担心的事情。为了完整起见,我想提及它。Never将是一个类似于之前存在的 Null (而不是null)在dart:core中定义的类型。这两个类都不能扩展、实现或混合,因此不打算使用它们。
本质上,Never意味着不允许任何类型,并且Never本身不能被实例化。Never中的List<Never>满足列表的泛型类型约束,这意味着它必须是。但是,List<Null>可以包含null:
// Only valid state: []
final neverList = <Never>[
  // Any value but Never here will be an error.
  5, // error
  null, // error

  Never, // not a value (compile-time error)
];

// Can contain null: [null]
final nullList = <Null>[
  // Any value but Null will be an error.
  5, // error
  null, // allowed

  Never, // not a value (compile-time error)
  Null, // not a value (compile-time error)
];
示例:编译器将为List<Never>推断const List<T>
就我而言,Never不应该被程序员使用。 (I was wrong)。
3. 了解更多
您可以阅读official article on sound null safety
此外,如开头所述,您可以play with it on DartPad

关于flutter - Dart 中的空安全性是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60068435/

相关文章:

flutter - SliverChildBuilderDelegate 使用 setState 更改数据时不重建其子级

android - MaterialApp窗口小部件的标题属性不起作用

uiscrollview - 如何以编程方式滚动 SingleChildScrollView?

flutter - 网络摄像头插件无法正常工作(仅适用于 iOS)

android - Flutter 缓存非常老的错误

flutter - 如何在 Flutter 中使用 Navigator.pushNamed 打开全屏对话框?

firebase - Flutter - 如何将 Firebase-Auth 用户凭据添加到新记录(FireStore 文档)?

constructor - Dart (/flutter ): Create function in initializer list

flutter - OnPressed 对字体颜色的影响

android - 如何在flutter中将列表对象发布到cloud firestore firebase