一、运算符
Dart 中,支持各种类型运算符,且其中的一些操作符还支持重载操作。
1. 算数运算符
Dart 中的算数运算符有以下几种:+
、-
、*
、/
、%
、~/
,通过以下示例说明:
main(){
var a = 21;
var b = 10;
var c;
c = a + b; //加法操作
print(c); //输出 31
c = a - b; //减法操作
print(c); //输出 11
c = a * b; //乘法操作
print(c); //输出 210
c = a / b; //除法操作,两个相除结果为double,即便两个整数相除也为double
print(c); //输出 2.1
c = a % b; //取余操作
print(c); //输出 1
c = a ~/ b; //取整操作
print(c); //输出 2
print(-c); //负数操作,输出 -2
}
Dart 支持自增与自减操作,如下:
main(){
var a, b, c;
a = 21;
b = 10;
c = a++ + b; //a参与运算完毕后自增加1
print(c); //输出 31
a = 21;
b = 10;
c = ++a + b; //a自增加1后参与运算
print(c); //输出 32
a = 21;
b = 10;
c = a-- + b; //a参与运算完毕后自减1
print(c); //输出 31
a = 21;
b = 10;
c = --a + b; //a自减1后参与运算
print(c); //输出 20
}
另外 +
运算符也可用于字符串连接。
2. 比较运算符
比较运算符有:==
、!=
、>
、<
、>=
、<=
。使用例子如下:
main(){
var a = 20;
var b = 30;
if(a == b) {
print("a等于b");
}else if(a != b){
print("a不等于b"); //输出 a不等于b
}
if(a > b) {
print("a大于b");
}else if(a < b) {
print("a小于b"); //输出 a小于b
}
if(a >= b) {
print("a大于等于b");
}else if(a <= b) {
print("a小于等于b"); //输出 a小于等于b
}
}
3. 类型运算符
Dart 中类型运算符有三种:is
、as
、is!
,用于运行时检查类型。
is
运算符用来判断数据是否属于某个类型,属于返回 true
,不属于返回 false
。如果ojb
实现了 T
定义的接口,则 obj is T
为 true
。
is!
运算符用来判断数据是否不属于某个类型,不属于返回 true
, 属于返回 false
。
as
运算符用来做类型转换,此转换并非真正的转换,而是把原对象当做目标对象使用,不会改变原对象。当使用 as
运算符时,应先确定原对象是否属于目标类型,如果不是目标类型的子类或实例不能使用 as
运算符。as
也可用于做指定库的前缀操作(后续会讲到)。
main(){
var str = "this is a string!";
if(str is String) {
print("str 是字符串");
}else{
print("str 不是字符串");
}
var a = 10;
if(a is! String) {
print("a 不是字符串");
}else{
print("a 是字符串");
}
var b =(a as num) + 10; //如不确定a是否为num的实例或子类,可以使用is操作符做先行判断。如无法转换会抛出异常
print(b);
}
4. 逻辑运算符
逻辑运算符是针对布尔值进行运算的运算符,包括:!
、||
、&&
。
!
逻辑非运算符,其只有一个操作数。当操作数布尔值为 true
时,运算结果为 false
,运算数布尔值为 false
,运算结果为 true
。
||
逻辑或运算符,有两个操作数。当操作数中至少有一个为 true
时,结果为 true
,操作数都为 false
,结果为 false
。
&&
逻辑与运算符,有两个操作数。当操作数中至少有一个为 false
时,结果为 false
,操作数都为 true
,结果为 true
。
||
和 &&
均为短路运算符。
main(){
print(!true); //输出 flase
print(!false); //输出 true
print(true || false); //输出 true
print(false || true); //输出 true
print(true || true); //输出 true
print(false || false);//输出 false
print(true && false); //输出 false
print(false && true); //输出 false
print(true && true); //输出 true
print(false && false);//输出 false
}
5. 条件运算符
条件运算符包括:?:
、??
或 ??=
。
main(){
var a = 10;
var b = 20;
var c = a>b ? a : b; //如果a大于b则返回a的值赋给c,否则返回b的值赋给c
print(c);
//?? 与 ??= 一样,为空运算符
print(a ?? 100); //输出 10 如果a为null则将100赋值给a,如果a不为null则使用a的值
var d;
print(d ??= 200); //输出200
}
6. 位运算符
位运算符是针对二进制位进行操作的运算符。包括:&
、|
、^
、~
、<<
、>>
。
&
按位与运算符,是将两个操作数的每一个二进制位分别做与运算,对应的两个二进制位都为1则结果为1,否则为0。
|
按位或运算符,是将两个操作数的每一个二进制位分别做或运算,对应的两个二进制位至少有一个为1则结果为1,否则为0。
^
按位异或运算符,是将两个操作数的每一个二进制位分别做异或运算,对应的两个二进制位相同(同为1或同为0)则结果为0,否则为1。
~
按位取反运算符,只有一个操作数,是将操作数的每一个二进制位进行取反操作,即1取反为0,0取反为1。
<<
按位左移运算符,是将操作数的每一个二进制位向左移动指定的位数。每左移一位相当于原数值乘2。
>>
按位右移运算符,是将操作数的每一个二进制位向右移动指定的位数。每右移一位相当于原数值除以2。
main(){
int a = 10; //二进制为00001010
int b = 5; //二进制为00000101
print(a & b); //运算后二进制为0000 0000,输出结果为 0
print(a | b); //运算后二进制为0000 1111,输出结果为 15
print(a ^ b); //运算后二进制为0000 1111,输出结果为 15
print(~a); //运算后二进制为1111 0101,输出结果为 -11 可以通过-(a+1)公式快速得出结果。
print(a << 2); //运算后二进制为0010 1000,输出结果为 40
print(b >> 2); //运算后二进制为0000 0001,输出结果为 1
}
7. 复合运算符
复合运算符是多种简单运算的复合,包括:+=
、-=
、*=
、/=
、~/=
、%=
、<<=
、>>=
、&=
、^=
、|=
。
main(){
double a = 10.0; //二进制为00001010
int b = 20; //二进制为00000101
print(a += 10); //输出(此时的a值) 20,0
print(a -= 10); //输出(此时的a值) 10,0
print(a *= 10); //输出(此时的a值) 100,0
print(a /= 10); //输出(此时的a值) 10,0
print(b ~/= 10); //输出(此时的b值) 2
print(b %= 10); //输出(此时的b值) 2
print(b <<= 2); //输出(此时的b值) 8
print(b >>= 2); //输出(此时的b值) 2
print(b &= 5); //输出(此时的b值) 0
print(b ^= 5); //输出(此时的b值) 5
print(b |= 5); //输出(此时的b值) 5
}
8. 级联运算符
级联运算符是 Dart 中比较高级的运算符,用于对同一对象执行一系列操作,使用 ..
表示。使用级联运算符可以减少中间变量的生成,如下:
main(){
List lst = List()
..add(1)
..add(2)
..addAll([3, 4, 5]);
print(lst);
}
级联运算符也可以嵌套使用。
9. 点运算符
点运算符用来对对象的属性和方法进行操作。使用点运算符操作对象中不存在的属性或方法时会抛出异常,同样也不能操作 null
对象,如果不确定对象是否为空,则可使用条件访问运算符 ?.
。如果需要操作的对象为空会返回 null
,否则正常操作。
main(){
var lst = [1, 2, 3];
print(lst.length); //输出 3
lst = null;
// print(lst.length); //运行此行会抛出异常
print(lst?.length); //输出 null
}
二、流程控制
流程控制语句与其他语言没有什么区别,下面简单的只列出代码,不做过多讲解。需要注意在 Dart 中条件的真假只有 true
和 false
,或它能得出 true
和 false
的表达式。
1. if 和 else
main(){
int score = 80;
if(score >= 100) {
print("满分");
}else if(score >= 60) {
print("及格");
}else{
print("不及格");
2. for 、while 、do while
main(){
List arr = [1, 2, 3, 4, 5];
//第一种for
for(int i = 0; i < arr.length; i++) {
print(arr[I]);
}
print("-----分割线-----");
//第二种for
for(var x in arr) {
print(x);
}
print("-----分割线-----");
int i = 0;
while(i < 5) {
print(arr[I]);
I++;
}
print("-----分割线-----");
i = 0;
do{
print(arr[I]);
I++;
}while(i < 5);
}
3. break 和 continue
break
用于跳出与 break
最近的循环,continue
用于跳出本次执行的循环。
main(){
List arr = [[1, 2], [3, 4, 5], [7, 8, 9]];
//正常的循环,输出1,2,3,4,5,6,7,8,9
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
print(arr[i][j]);
}
}
//break,当j == 1时跳出里层for循环,所以最终只打印了数组的1,3,7
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
if(j == 1) {
break;
}
print(arr[i][j]);
}
}
//continue 当j==1时,跳出单次循环,继续下次循环 输出 1,3,5,7,9
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
if(j == 1) {
continue;
}
print(arr[i][j]);
}
}
}
4. switch 和 case
Dart 中 switch
参数可以使用整型、字符串或编译时常量,case
后对象必须全部是同一类的实例。通常,每个非空 case
子句都以 break
结尾。结束非空 case
子句的其他有效方法为 continue
、throw
、return
。
main(){
String single = "e";
switch(single) {
case "h":
print("h");
break;
case "e":
print("e");
break;
case "l":
print("l");
break;
case "o":
print("o");
break;
default:
print("error");
break;
}
}
可以使用 continue
来进行跳转执行,如下:
main(){
String single = "e";
switch(single) {
case "h":
print("h");
break;
case "e":
print("e"); //输出 e
continue jumpOther;
case "l":
print("l");
break;
jumpOther:
case "o":
print("o"); //输出 o
break;
default:
print("error");
break;
}
}
上述代码在 case "o":
上添加了一个 jumpOther
标签,并在 case "e":
处通过 continue jumpOther
进行了调用,输出e后继续执行o。
三、异常处理
异常是一种错误,在程序的运行过程中造成异常的情况有很多,如果不加以识别和控制将引发程序被挂起,造成程序崩溃而结束程序。Dart 中的异常都是未经检查的异常。Dart 中提供了 Exception
和 Error
类型,以及许多预定义的子类型,也可以自定义异常。Dart 程序可以抛出任何非 null
对象,而非仅限于 Exception
和 Error
。
抛出异常
main(){
throw FormatException("这是一个FormatException");
// print("程序结束"); //此处不会被执行
}
//抛出的异常 Unhandled exception: FormatException: 这是一个FormatException
main(){
throw 400; //抛出自定义的任意非null异常
// print("程序结束"); //此处不会被执行
}
//抛出的异常 Unhandled exception: 400
捕获异常
捕获异常的目的在于组织异常的传播,并进行一定的处理措施。可以将有可能发生异常的代码放在 try
代码块中并使用 catch
捕获。如果需要捕获的异常不止一种,可以使用多个 catch
。基本形式如下:
main(){
try{
throw "抛出一个字符串提示异常";
}on RangeError catch(e) {
// print(e);
}on String catch(e) {
print("字符串异常");
}catch(e, s) { //e为异常信息,s为异常的栈跟踪信息
print("其他异常:$e");
print("栈信息:$s");
}
}
上面代码主动抛出一个异常,是一句字符串的提示信息,所以下面将执行 print("字符串异常")
,on
后接一个异常的具体类型,因为我们抛出的是字符串异常信息,所以会进入 on String catch(e)
,当然可以定义其他具体异常类型。如果捕获的异常并非 on
后接的异常类型,则进入最后的未定义具体类型的异常。catch
方法可以有一个参数参数或两个参数,一个参数时,参数为异常提示信息,两个参数时,第一个参数为异常提示信息,第二个为异常的堆栈信息(StackTrace
对象)。
main(){
List arr = [1, 2, 3];
try{
print(arr[3]);
}on int catch(e) {
print(e);
}on String catch(e) {
print("字符异常");
}catch(e, s) { //e为异常信息,s为异常的栈跟踪信息
print("其他异常:$e");
print("栈信息:$s");
}
}
异常异常类型为 RangeError
类型,所以通过 on
捕获的 int
和 String
类型都不对,进入最后的 catch
。
即使捕获到了异常,开发者也可以根据具体情况决定是处理、忽略还是继续抛出异常,如果需要继续抛出,可使用 rethrow
关键字。 rethrow
允许部分处理异常或直接继续抛出异常给其他方法处理。
main(){
List arr = [1, 2, 3];
try{
try{
print(arr[3]);
}catch(e){
rethrow;
}
}on int catch(e) {
print(e);
}on String catch(e) {
print("1");
}catch(e, s) { //e为异常信息,s为异常的栈跟踪信息
print("其他异常:$e");
print("栈信息:$s");
}finally {
print("善后处理或抛出异常后需要继续执行的代码");
}
}
此外有时需要无论是否抛出异常都执行指定的代码,则需要使用到 finally
关键字,如下:
main(){
List arr = [1, 2, 3];
try{
print(arr[3]);
}on int catch(e) {
print(e);
}on String catch(e) {
print("字符异常");
}
catch(e, s) { //e为异常信息,s为异常的栈跟踪信息
print("其他异常:$e");
print("栈信息:$s");
}finally {
print("善后处理或抛出异常后需要继续执行的代码");
}
}
四、断言
Dart 中使用 assert
来调试程序的执行,使用 assert
如果布尔条件为假,则中断正常执行,并抛出异常。assert
中的条件是任何可以转化为布尔类型的对象,即使函数也可以。
main(){
print("执行第一步"); //输出 执行第一步
assert(1 == 1); //条件为真,继续执行
print("执行第二步"); //输出 执行第二步
assert(1 == 2); //条件为假,抛出异常
print("执行第三步"); //不执行此处
}
//以上会抛出如下异常:
//执行第一步
//执行第二步
//Unhandled exception:
//Failed assertion: line 5 pos 10: '1 == 2': is not true.
//#0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:42:39)
//#1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:38:5)
//#2 main
//Dart/demo1.dart:5
//#3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:307:19)
//#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
//Exited (255)
可以附加自己的说明在 assert
里,如下:
main(){
assert(1 == 2, "这里的条件不成立,1不等2");
print("不会执行");
}
assert
可以有两个参数,第一个为任意可以解析为布尔值的表达式,第二个为附加说明信息。
在生产代码中,assert
将被忽略,并且不会评估断言的参数。
PS:如果您使用的是 VSCode 来运行 以上断言代码,如果安装有 Code Runner 插件并使用此插件来运行代码,则断言不会执行,需要通过 Debug -> Start Debugging 或 Debug -> Start Without Debugging 来运行代码才会执行断言代码。
更多内容,请关注公众号持续关注。
wchatq2.png
网友评论