[英]What is Null Safety in Dart?
空安全/不可空(默认情况下),简称 NNBD,功能目前可以在nullsafety.dartpad.dev找到。
请记住,您可以在这里阅读完整的规范和完整的路线图。 现在, Dart也正式宣布了声音零安全性。
void main() {
String word;
print(word); // illegal
word = 'Hello, ';
print(word); // legal
}
正如您在上面看到的,默认情况下不可为空的变量意味着通常声明的每个变量都不能为null
。 因此,在变量被赋值之前访问变量的任何操作都是非法的。
此外,也不允许将null
分配给不可为 null 的变量:
void main() {
String word;
word = null; // forbidden
world = 'World!'; // allowed
}
如果变量是non-nullable ,您可以确定它永远不会为null
。 因此,您永远不需要事先检查它。
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
}
见late
以下修改此行为。
?
) 您可以通过附加问号来使用可为空类型?
到变量类型:
class Foo {
String word; // forbidden
String? sentence; // allowed
}
可空变量在使用前不需要初始化。 默认情况下,它被初始化为null
:
void main() {
String? word;
print(word); // prints null
}
!
追加!
如果e
为空,则到任何变量e
将引发运行时错误,否则将其转换为不可为空的值v
。
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
关键字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
将引发运行时错误。
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
。
required
以前是注释( @required
),现在作为修饰符内置。 它允许将任何命名参数(对于函数或类)标记为required
,这使它们不可为空:
void allowed({required String word}) => null;
这也意味着如果一个参数应该是non-nullable ,它需要被标记为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;
?[]
为索引运算符[]
添加了空感知?[]
运算符:
void main() {
List<int>? list = [1, 2, 3];
int? x = list?[0]; // 1
}
另请参阅有关语法决策的这篇文章。
?..
级联运算符现在还有一个新的空感知运算符: ?..
。
它会导致以下级联操作仅在接收者不为 null 时执行。 因此, ?..
必须是级联序列中的第一个级联运算符:
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);
}
Never
下面的解释很烂。 阅读“了解零安全性”中的“顶部和底部”以获得很好的效果。
为避免混淆:这不是开发人员必须担心的事情。 为了完整起见,我想提及它。
Never
将成为dart:core
定义的先前存在的Null
(非null
)类型。 这两个类都不能扩展、实现或混合,因此不打算使用它们。
本质上, Never
意味着不允许任何类型,而且Never
本身不能被实例化。
List<Never>
中的 Nothing but Never
满足List<Never>
的泛型类型约束,这意味着它必须为empty 。 但是, 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)
];
示例:编译器将为空的const List<T>
推断List<Never>
const List<T>
。
就我而言, Never
不应该被程序员使用。 ( 我错了)。
您可以阅读有关 sound null safety的官方文章。
此外,正如开头提到的,您可以在 DartPad 上使用它。
如果您希望此字段为必填字段,则使用必填关键字,否则您只需要输入“?”。 像这样
const phonefield({
Key? key,required this.onchanged,
}) : super(key: key);
final ValueChanged<String>onchanged;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.