什么是Dart中的Null安全性?

时间:2020-02-05 03:01:22

标签: flutter dart

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

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

它如何工作?在哪里可以尝试?

2 个答案:

答案 0 :(得分:84)

1。空安全性/不可为空(默认)

当前可以在nullsafety.dartpad.dev上找到空安全性/不可空性(默认情况下),简短的NNBD功能。

请记住,您可以阅读full spec herefull roadmap here。现在,声音无效的安全性也已经officially announced for Dart


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

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

  word = 'Hello, ';
  print(word); // legal
}

如上所述,变量默认为不可为空 ,这意味着通常不能声明的每个变量均为{{ 1}}。因此,在赋值之前访问变量的任何操作都是非法的。
此外,也不允许将null分配给不可为空的变量:

null

2.1.1。这对我有什么帮助?

如果变量不可为空,则可以确保它永远不会void main() { String word; word = null; // forbidden world = 'World!'; // allowed } 。因此,您无需事先检查。

null

2.1.2。记住

如果

类中的实例字段不可为空,则必须对其进行初始化:

int number = 4;

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

  int sum = number + 2; // allowed because number is also non-nullable
}

请参见下面的class Foo { String word; // forbidden String sentence = 'Hello, World!'; // allowed } 来修改此行为。

2.2。可空类型(late

您可以通过将问号?附加到变量类型来使用可空类型

?

可空变量无需初始化即可使用。默认情况下,它初始化为class Foo { String word; // forbidden String? sentence; // allowed }

null

2.2.2。 void main() { String? word; print(word); // prints null }

如果将!为null,则将 ! 附加到任何变量e会引发运行时错误,否则会将其转换为不可为空e

v

2.3。 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 }

关键字late可用于标记稍后将初始化的变量,即不是在声明它们时而是在访问它们时。这也意味着我们可以拥有不可空的 instance字段,这些字段稍后会初始化:

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'; } } 会引发运行时错误。

2.3.1。 word

现在也可以将最终变量标记为更晚了:

late final

这里late final int x = heavyComputation(); 仅在访问heavyComputation后才被调用。另外,您也可以声明一个没有初始化程序的x,这与只有一个late final变量的情况相同,但是只能分配一次。

late

请注意,带有初始化程序的所有顶级 static 变量现在都将被late final int x; // w/e x = 5; // allowed x = 6; // forbidden 求值,无论它们是late

2.4。 final

以前是注释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;

2.5。 void baz({int? x}) => null;

为索引运算符?[]添加了空感知的?[]运算符:

[]

另请参阅this article about the syntax decision

2.5.1。 void main() { List<int>? list = [1, 2, 3]; int? x = list?[0]; // 1 }

级联运算符现在还具有一个新的空感知运算符:?..

仅当收件人为不为空时,才会执行以下级联操作。因此,?..必须是级联序列中的第一个级联运算符:

?..

2.6。 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); }

以下解释很糟糕。阅读"Top and bottom" from "Understanding null safety" 读一本书。

为避免混淆:开发人员不必担心这一点。为了完整起见,我想提一下。

Never的类型将类似于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>不应由程序员使用。 (I was wrong)。

3。了解更多

您可以阅读official article on sound null safety
此外,如开头所述,您可以play with it on DartPad

答案 1 :(得分:-3)

如果您希望此字段为必填项,则使用必填关键字,否则您只需输入“?”。像这样

const phonefield({
    Key? key,required this.onchanged,

  }) : super(key: key);
  final  ValueChanged<String>onchanged;
相关问题