对比一般非空判断和 dart 特有语法糖进行优雅的避空

2019-09-1410:29:00编程语言入门到精通Comments8,884 views字数 2653阅读模式

空指针异常应该是基本都会遇到过的异常,而且这个异常出现的概率还比较大。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

但是,空指针异常又是最容易解决的异常,因为只要加个非空判断就可以避免了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

本篇通过对比一般非空判断和 dart 特有的语法糖告诉你如何使用 dart 进行优雅的避空。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

目录

对比一般非空判断和 dart 特有语法糖进行优雅的避空

1. dart 在线编辑器

一般一些简单的 dart 测试我们可以直接用在线编辑器来做测试和验证。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

下面给大家介绍的两个都是官网的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

dart 在线运行器主页版: ?
www.dartlang.org/guides/get-…文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

dart 在线运行器全屏版: ?
dartpad.dartlang.org/null文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

其中全屏版就是在主页版里面点击全屏按钮就打开了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

所以可以认为是一样的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

但是笔者使用起来的不同如下,大家可以根据自己的感受选择。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

主页版:
优点:运行输出结果较全屏版快。
缺点:输出结果区域较小,超出需要滑动查看。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

全屏版:
优点:输出结果区域大。可以直观看到结果。 缺点:运行输出结果较主页版慢。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

2. dart ?.

dart 语法糖 ?.文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

它的意思是左边如果为空返回 null,否则返回右边的值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

A?.B
如果 A 等于 null,那么 A?.B 为 null
如果 A 不等于 null,那么 A?.B 等价于 A.B文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

Sample:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

void main() {
  Animal animal = new Animal('cat');
  Animal empty = null;
  
  //animal 非空,返回 animal.name 的值 cat
  print(animal?.name);
  //empty 为空,返回 null
  print(empty?.name);
  
  //animal 非空,可以直接访问 animal.name 的值 cat
  print(animal.name);
  //empty 为空,抛出异常
  print(empty.name);
}

class Animal {
  final String name;
  Animal(this.name);
}
复制代码

大家拷贝代码然后替换在线编辑器的内容,运行后会看到如下输出:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

cat
null
cat
Uncaught exception:
Cannot read property 'get$name' of null
复制代码

可以看到假设左边不为空,不管是使用**?.还是直接用我们熟悉的.访问变量都是没问题的。
但是如果左边为空,使用
?.会返回null**。但是直接使用**.**会直接抛出异常。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

3. dart ??

dart 语法糖 ??文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

它的意思是左边如果为空返回右边的值,否则不处理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

A??B
如果 A 等于 null,那么 A??B 为 B
如果 A 不等于 null,那么 A??B 为 A文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

以上面为例子,假设我们上面要求当 empty 为空时,默认值输出 unknown。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

那么可以修改如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

//empty 为空,返回 null
print(empty?.name);
复制代码

改为文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

//empty 为空,本来要返回 null,由于有 ??,返回 unknown
print(empty?.name??'unknown');
复制代码

这样就不会返回 null 而是返回 unknown。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

同样的大家可以试下返回 cat 的语句如果加上这个会怎样,可以预见是不会改变的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

4. dart ?. ?? 优雅所在

这边举例说明下使用 ?. ?? 语法糖和不使用的对比。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

void main() {
  C c = new C('Case 1');
  B b = new B(c);
  A a = new A(b);
  
//   C c = new C(null);
//   B b = new B(c);
//   A a = new A(b);
  
//   C c = new C('Case 2');
//   B b = null;
//   A a = new A(b);
  
  //直接使用.来最终获取 c 的变量 value
  if (a != null && a.bMember != null && a.bMember.cMember != null) {
    print(a.bMember.cMember.value);
  } else {
    print(null);
  }
  
  //直接使用.来最终获取 c 的变量 value,为空时返回 unknown
  if (a != null && a.bMember != null && a.bMember.cMember != null) {
    String value = a.bMember.cMember.value;
    if (value == null) {
      value = 'unknown';
    }
    print(value);
  } else {
    print('unknown');
  }
  
  //dart 使用?.来最终获取 c 的变量 value
  print(a?.bMember?.cMember?.value);
  //dart 使用?.来最终获取 c 的变量 value,为空时使用 ?? 返回 unknown
  print(a?.bMember?.cMember?.value??'unknown');
}

class A {
  final B bMember;
  A(this.bMember);
}

class B {
  final C cMember;
  B(this.cMember);
}

class C {
  final String value;
  C(this.value);
}
复制代码

这里面有三个 case,另外两个 case 暂时注释掉。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

这三个 case 的结果分别为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

Case 1
Case 1
Case 1
Case 1
复制代码
null
unknown
null
unknown
复制代码
null
unknown
null
unknown
复制代码

可以看到 dart 的语法糖很优雅,一行全搞定。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

5. print 方法遇到 null

下面这个例子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

void main() {
    String a = null;
    print('exception='+a);
}
复制代码

你觉得结果是 exception=null 吗?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

对比一般非空判断和 dart 特有语法糖进行优雅的避空

结果是文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

Uncaught exception:
Invalid argument: null
复制代码

原因是因为 print 里面连接的必须是字符串。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

因为这里 a 确实是字符串,所以编辑器没有报错。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

假设这里 a 为一个对象 A 的变量,会报如下提示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

The argument type 'A' can't be assigned to the parameter type 'String'.
复制代码

那我们怎么处理?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

有两种方法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

方法一:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

void main() {
    String a = null;
    print('exception='+'$a');
}
复制代码

方法二:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

void main() {
    String a = null??'null';
    print('exception='+a);
}
复制代码

注意下面的写法是不行的,原因是 ?? 优先级没有 + 高。需要加小括号。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

void main() {
    String a = null;
    print('exception='+a??'null');
}

作者:安卓小煜
来源:掘金文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/16435.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/16435.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定