[Flutter]flutter基础之Dart语言基础(二)

一、运算符

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 中类型运算符有三种:isasis! ,用于运行时检查类型。

is 运算符用来判断数据是否属于某个类型,属于返回 true ,不属于返回 false 。如果ojb 实现了 T 定义的接口,则 obj is Ttrue
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 中条件的真假只有 truefalse ,或它能得出 truefalse 的表达式。

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 子句的其他有效方法为 continuethrowreturn

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 中提供了 ExceptionError 类型,以及许多预定义的子类型,也可以自定义异常。Dart 程序可以抛出任何非 null 对象,而非仅限于 ExceptionError

抛出异常

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 捕获的 intString 类型都不对,进入最后的 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.  (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 来运行代码才会执行断言代码。

你可能感兴趣的:([Flutter]flutter基础之Dart语言基础(二))