如果我在nullsafety.dartpad.dev中编写以下代码:
void main() {
String? name = 'Bob';
print(name.length);
}
我收到以下编译时错误:以及以下运行时错误:
Type promotion on null checks文档说:
题
上面的代码中
name
不可能为null。该文档还说,分配应该引起类型提升。我是误解类型提升还是DartPad中的错误?澄清度
由于有两个答案为错误消息提供了解决方法,因此我应该澄清,我并不是要解决上面的编码问题。相反,我是说我认为代码应该可以正常工作。但事实并非如此。为什么不?
最佳答案
该答案是对原始问题中添加的赏金的回应。赏金如下:
串? vs StringString?
类型可以包含字符串或null
。这里有些例子:
String? string1 = 'Hello world';
String? string2 = 'I ❤️ Dart';
String? string3 = '';
String? string4 = null;
另一方面,String类型只能包含字符串(即,一旦null安全是Dart的一部分)。它不能包含null
。这里有些例子:String string1 = 'Hello world';
String string2 = 'I ❤️ Dart';
String string3 = '';
如果您尝试执行以下操作:String string4 = null;
您将得到编译时错误:A value of type 'Null' can't be assigned to a variable of type 'String'.
String
类型不能是null
,不能像int
这样的3
还是bool
这样的true
。这就是零安全性的全部含义。如果您有一个类型为String
的变量,则可以确保该变量永远不会是null
。类型推广的工作原理
如果编译器可以从逻辑上确定可为null的类型(如
String?
)将永远不是null
,则它将编译(或提升)该类型为其不可为null的对应类型(如String
)。这是真实的一个示例:
void printNameLength(String? name) {
if (name == null) {
return;
}
print(name.length);
}
尽管参数name
可为空,但如果实际上是null
,则该函数会提前返回。到name.length
时,编译器肯定会知道name
不能是null
。因此,编译器将名称从String?
提升为String
。表达式name.length
将永远不会导致崩溃。一个类似的例子在这里:
String? name;
name = 'Bob';
print(name.length);
尽管name
在此处也是可为空的,但是字符串文字'Bob'
显然非空。这也将name
提升为不可空的String
。最初的问题涉及以下方面:
String? name = 'Bob';
print(name.length);
似乎这也应该将名称提升为不可空的String
,但事实并非如此。正如@lrn(一位Google工程师)在comments中指出的那样,这是一个错误,当出现null安全性时,它也将像前面的示例一样工作。也就是说,name
将被提升为不可空的String
。进一步阅读
关于dart - 分配非空值文字时的空安全类型提升,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63531488/