前言
对于每一个程序员来说,空指针异常应该是基本都会遇到过的异常,而且这个异常出现的概率还比较大。
但是,空指针异常又是最容易解决的异常,因为只要加个非空判断就可以避免了。
本篇通过对比一般非空判断和 dart 特有的语法糖告诉你如何使用 dart 进行优雅的避空。
1. dart 在线编辑器
一般一些简单的 dart 测试我们可以直接用在线编辑器来做测试和验证。
下面给大家介绍的两个都是官网的。
dart 在线运行器主页版:
https://www.dartlang.org/guides/get-started
dart 在线运行器全屏版:
https://dartpad.dartlang.org/null
其中全屏版就是在主页版里面点击全屏按钮就打开了。
所以可以认为是一样的。
但是笔者使用起来的不同如下,大家可以根据自己的感受选择。
主页版:
优点:运行输出结果较全屏版快。
缺点:输出结果区域较小,超出需要滑动查看。
全屏版:
优点:输出结果区域大。可以直观看到结果。
缺点:运行输出结果较主页版慢。
2. dart ?.
dart 语法糖 ?.
它的意思是左边如果为空返回 null,否则返回右边的值。
A?.B
如果 A 等于 null,那么 A?.B 为 null
如果 A 不等于 null,那么 A?.B 等价于 A.B
Sample:
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); }
大家拷贝代码然后替换在线编辑器的内容,运行后会看到如下输出:
catnullcat Uncaught exception: Cannot read property 'get$name' of null
可以看到假设左边不为空,不管是使用?.还是直接用我们熟悉的.访问变量都是没问题的。
但是如果左边为空,使用?.会返回null。但是直接使用.会直接抛出异常。
3. dart ??
dart 语法糖 ??
它的意思是左边如果为空返回右边的值,否则不处理。
A??B
如果 A 等于 null,那么 A??B 为 B
如果 A 不等于 null,那么 A??B 为 A
以上面为例子,假设我们上面要求当 empty 为空时,默认值输出 unknown。
那么可以修改如下:
//empty 为空,返回 nullprint(empty?.name);
改为
//empty 为空,本来要返回 null,由于有 ??,返回 unknownprint(empty?.name??'unknown');
这样就不会返回 null 而是返回 unknown。
同样的大家可以试下返回 cat 的语句如果加上这个会怎样,可以预见是不会改变的。
4. dart ?. ?? 优雅所在
这边举例说明下使用 ?. ?? 语法糖和不使用的对比。
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 暂时注释掉。
这三个 case 的结果分别为:
Case 1Case 1Case 1Case 1
nullunknownnullunknown
nullunknownnullunknown
可以看到 dart 的语法糖很优雅,一行全搞定。
5. print 方法遇到 null
下面这个例子:
void main() { String a = null; print('exception='+a); }
你觉得结果是 exception=null 吗?
结果是
Uncaught exception: Invalid argument: null
原因是因为 print 里面连接的必须是字符串。
因为这里 a 确实是字符串,所以编辑器没有报错。
假设这里 a 为一个对象 A 的变量,会报如下提示:
The argument type 'A' can't be assigned to the parameter type 'String'.
那我们怎么处理?
有两种方法。
方法一:
void main() { String a = null; print('exception='+'$a'); }
方法二:
void main() { String a = null??'null'; print('exception='+a); }
注意下面的写法是不行的,原因是 ?? 优先级没有 + 高。需要加小括号。
void main() { String a = null; print('exception='+a??'null'); }
6. 牛刀小试
知识学以致用才能够巩固。
因此这边出了小题目给大家测试是否完全掌握本篇内容。
答案组成了支付宝口令红包哦~
微信公众号回复「牛刀小试」获取题目。
或者直接点击菜单栏目录->牛刀小试获取。
温馨提示:
如果你输入 3 次还是提示错误(错误过多口令红包会暂时不可用哦),有两种情况。
第一种就是答案错了。
第二种就是领取完了。
作者:AndroidTraveler
链接:https://www.jianshu.com/p/1fdb8f1b2df6
共同学习,写下你的评论
评论加载中...
作者其他优质文章