late
late关键字是Dart 2.12及更高版本中引入的一个特性,用于延迟初始化。它主要用于两种场景:非空类型的延迟初始化和显式的懒加载
非空类型的延迟初始化
在引入空安全特性之后,Dart要求所有的变量在使用前都必须初始化。然而,在某些情况下,我们可能无法在声明变量的同时初始化它,比如依赖于构造函数参数或者需要进行异步操作来获取初始值。这时,late关键字就派上了用场。通过late标记的变量,Dart允许你稍后初始化这个变量,同时确保在第一次使用前已被初始化,否则会抛出异常。
class MyClass {
late String description;
void setDescription(String desc) {
description = desc;
}
}
显式的懒加载
late还可用于变量的懒加载,即变量在第一次被访问时才进行初始化。这对于初始化开销较大的变量非常有用,可以在确实需要这些变量的时候才去创建它们,从而提高程序的性能。
class MyDatabase {
late final HeavyDatabase _database = HeavyDatabase();
HeavyDatabase get database => _database;
}
在这个例子中,_database变量只会在第一次访问database属性时被初始化,而不是在MyDatabase类的实例被创建时。
注意事项
- 使用
late时需要小心,因为如果在变量被正确初始化之前访问它,会抛出LateInitializationError异常。 late不应该被用作绕过空安全的手段。确保在第一次访问变量之前已经对其进行了初始化。- 对于懒加载的场景,考虑初始化开销和访问频率,决定是否使用
late是一个好的选择。
运算符
基本运算符
dart中的基本运算符和其他语言区别不大,比较特殊的有一个检查两个引用是否指向同一个对象identical
// 赋值
var a = 1;
int? b;
b ??= 2; // 如果 b 为空的话就把 2 赋值给 b
a += 0; // a=a+0
//算数运算
print(a + b);
print(a - b);
print(a * b);
print(a / b);
print(a % b); // 取余
print(a ~/ b); // 取整
a ++ // 先运算再自增
a -- //先运算再自减
-- a // 先自减再运算
++ a // 先自增再运算
//关系运算
print(a == b);
print(a >= b);
print(a <= b);
print(a != b);
identical(DateTime.now(), DateTime.now()); // 判断两个对象是否相等
//逻辑运算符
|| && !
类型运算符
- as 类型转换
as运算符是一种强制类型转换,如果类型不兼容,将导致CastError。因此,在使用as时,确保您知道表达式的确切类型,并确保它与目标类型兼容
Animal animal = Dog();
Dog dog = animal as Dog;
dog.bark(); // 输出: Dog is barking
- is 是否为某个类型,是返回true
- is! 不是某个类型,不是返回true
条件访问与断言
- ?[] 访问list指定位置成员,若list为空则返回null
- ?. 访问对象指定属性或方法,若对象为空则返回null
- a.b! 指定返回值为非null
- ??
print(nullableString ?? 'alternate');
print(nullableString != null ? nullableString : 'alternate');
- ??=
// Both of the following set nullableString to 'alternate' if it is null
nullableString ??= 'alternate';
nullableString = nullableString != null ? nullableString : 'alternate';
三目运算符
条件 ? 表达式 1 : 表达式 2
与其他语言类似,c此处条件必须是一个bool
级联运算符
级联运算符 (.., ?..) 可以让你在同一个对象上连续调用多个对象的变量或方法
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
-------------------------
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();
//使用 空判断 级联操作符 (?..)可以确保级联操作均在实例不为 null 时执行。
//使用空判断级联后,也不再需要 button 变量了:
querySelector('#confirm')
?..text = 'Confirm'
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'))
..scrollIntoView();
展开运算符
//你可以使用扩展操作符(...)将一个 List 中的所有元素插入到另一个 List 中:
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
//如果扩展操作符右边可能为 null ,你可以使用 null-aware 扩展操作符(...?)来避免产生异常:
var list2 = [0, ...?list];
assert(list2.length == 1);
判空与空安全
判空
var str = '';
if (str.isEmpty) {
print(' 判断为空字符串');
}
var _null = null;
if (_null == null) {
print('判断为 null');
}
var _null = null;
if (_null == null) {
print('判断为 null');
}
空安全
Dart 目前支持控安全机制,也就是说除非我们声明它可空,否则它们的值不能为空
声明可空的方式就是在类型前面加个问号:
int? count;
count = null;
如果我们知道一个值不可能为空,但是 Dart 判断可能为空,那就用!表示非空断言
String? getData(String? data) {
if (data is String) {
return 'this is string data';
}
return null;
}
String a = getData('12131'); //报错
String a = getData('12131')!; //正常