[Flutter]flutter基礎(chǔ)之Dart語言基礎(chǔ)(二)

一、運算符

Dart 中,支持各種類型運算符,且其中的一些操作符還支持重載操作。

1. 算數(shù)運算符

Dart 中的算數(shù)運算符有以下幾種:+ 、-* 、/% 、~/ ,通過以下示例說明:

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;  //除法操作,兩個相除結(jié)果為double,即便兩個整數(shù)相除也為double
  print(c);   //輸出 2.1
  c = a % b;  //取余操作
  print(c);   //輸出 1
  c = a ~/ b; //取整操作
  print(c);   //輸出 2
  print(-c);  //負(fù)數(shù)操作,輸出 -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 運算符用來判斷數(shù)據(jù)是否屬于某個類型,屬于返回 true ,不屬于返回 false 。如果ojb 實現(xiàn)了 T 定義的接口,則 obj is Ttrue
is! 運算符用來判斷數(shù)據(jù)是否不屬于某個類型,不屬于返回 true , 屬于返回 false
as 運算符用來做類型轉(zhuǎn)換,此轉(zhuǎn)換并非真正的轉(zhuǎn)換,而是把原對象當(dāng)做目標(biāo)對象使用,不會改變原對象。當(dāng)使用 as 運算符時,應(yīng)先確定原對象是否屬于目標(biāo)類型,如果不是目標(biāo)類型的子類或?qū)嵗荒苁褂?as 運算符。as 也可用于做指定庫的前綴操作(后續(xù)會講到)。

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操作符做先行判斷。如無法轉(zhuǎn)換會拋出異常
  print(b);
}
4. 邏輯運算符

邏輯運算符是針對布爾值進(jìn)行運算的運算符,包括:!||&& 。

! 邏輯非運算符,其只有一個操作數(shù)。當(dāng)操作數(shù)布爾值為 true 時,運算結(jié)果為 false ,運算數(shù)布爾值為 false,運算結(jié)果為 true
|| 邏輯或運算符,有兩個操作數(shù)。當(dāng)操作數(shù)中至少有一個為 true 時,結(jié)果為 true ,操作數(shù)都為 false ,結(jié)果為 false 。
&& 邏輯與運算符,有兩個操作數(shù)。當(dāng)操作數(shù)中至少有一個為 false 時,結(jié)果為 false ,操作數(shù)都為 true ,結(jié)果為 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. 位運算符

位運算符是針對二進(jìn)制位進(jìn)行操作的運算符。包括:&| 、^~ 、<< 、>>

& 按位與運算符,是將兩個操作數(shù)的每一個二進(jìn)制位分別做與運算,對應(yīng)的兩個二進(jìn)制位都為1則結(jié)果為1,否則為0。
| 按位或運算符,是將兩個操作數(shù)的每一個二進(jìn)制位分別做或運算,對應(yīng)的兩個二進(jìn)制位至少有一個為1則結(jié)果為1,否則為0。
^ 按位異或運算符,是將兩個操作數(shù)的每一個二進(jìn)制位分別做異或運算,對應(yīng)的兩個二進(jìn)制位相同(同為1或同為0)則結(jié)果為0,否則為1。
~ 按位取反運算符,只有一個操作數(shù),是將操作數(shù)的每一個二進(jìn)制位進(jìn)行取反操作,即1取反為0,0取反為1。
<< 按位左移運算符,是將操作數(shù)的每一個二進(jìn)制位向左移動指定的位數(shù)。每左移一位相當(dāng)于原數(shù)值乘2。
>> 按位右移運算符,是將操作數(shù)的每一個二進(jìn)制位向右移動指定的位數(shù)。每右移一位相當(dāng)于原數(shù)值除以2。

main(){ 
  int a = 10;  //二進(jìn)制為00001010
  int b = 5;   //二進(jìn)制為00000101  

  print(a & b);  //運算后二進(jìn)制為0000 0000,輸出結(jié)果為 0
  print(a | b);  //運算后二進(jìn)制為0000 1111,輸出結(jié)果為 15 
  print(a ^ b);  //運算后二進(jìn)制為0000 1111,輸出結(jié)果為 15
  print(~a);     //運算后二進(jìn)制為1111 0101,輸出結(jié)果為 -11  可以通過-(a+1)公式快速得出結(jié)果。
  print(a << 2); //運算后二進(jìn)制為0010 1000,輸出結(jié)果為 40
  print(b >> 2); //運算后二進(jìn)制為0000 0001,輸出結(jié)果為 1
}
7. 復(fù)合運算符

復(fù)合運算符是多種簡單運算的復(fù)合,包括:+= 、-= 、*=/= 、~/= 、%= 、<<= 、>>= 、&=^= 、|= 。

main(){ 
  double a = 10.0;  //二進(jìn)制為00001010
  int b = 20;   //二進(jìn)制為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. 級聯(lián)運算符

級聯(lián)運算符是 Dart 中比較高級的運算符,用于對同一對象執(zhí)行一系列操作,使用 .. 表示。使用級聯(lián)運算符可以減少中間變量的生成,如下:

main(){ 
  List lst = List()
  ..add(1)
  ..add(2)
  ..addAll([3, 4, 5]);
  print(lst);
}

級聯(lián)運算符也可以嵌套使用。

9. 點運算符

點運算符用來對對象的屬性和方法進(jìn)行操作。使用點運算符操作對象中不存在的屬性或方法時會拋出異常,同樣也不能操作 null 對象,如果不確定對象是否為空,則可使用條件訪問運算符 ?. 。如果需要操作的對象為空會返回 null,否則正常操作。

main(){ 
  var lst = [1, 2, 3];
  print(lst.length);  //輸出 3
  lst = null;
  // print(lst.length);  //運行此行會拋出異常
  print(lst?.length); //輸出 null
}

二、流程控制

流程控制語句與其他語言沒有什么區(qū)別,下面簡單的只列出代碼,不做過多講解。需要注意在 Dart 中條件的真假只有 truefalse ,或它能得出 truefalse 的表達(dá)式。

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 最近的循環(huán),continue 用于跳出本次執(zhí)行的循環(huán)。

main(){
  List arr = [[1, 2], [3, 4, 5], [7, 8, 9]];

  //正常的循環(huán),輸出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,當(dāng)j == 1時跳出里層for循環(huán),所以最終只打印了數(shù)組的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 當(dāng)j==1時,跳出單次循環(huán),繼續(xù)下次循環(huán) 輸出 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 參數(shù)可以使用整型、字符串或編譯時常量,case 后對象必須全部是同一類的實例。通常,每個非空 case 子句都以 break 結(jié)尾。結(jié)束非空 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 來進(jìn)行跳轉(zhuǎn)執(zhí)行,如下:

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 標(biāo)簽,并在 case "e": 處通過 continue jumpOther 進(jìn)行了調(diào)用,輸出e后繼續(xù)執(zhí)行o。

三、異常處理

異常是一種錯誤,在程序的運行過程中造成異常的情況有很多,如果不加以識別和控制將引發(fā)程序被掛起,造成程序崩潰而結(jié)束程序。Dart 中的異常都是未經(jīng)檢查的異常。Dart 中提供了 ExceptionError 類型,以及許多預(yù)定義的子類型,也可以自定義異常。Dart 程序可以拋出任何非 null 對象,而非僅限于 ExceptionError 。

拋出異常

main(){
  throw FormatException("這是一個FormatException");
  // print("程序結(jié)束");  //此處不會被執(zhí)行
}

//拋出的異常 Unhandled exception: FormatException: 這是一個FormatException
main(){
  throw 400;  //拋出自定義的任意非null異常
  // print("程序結(jié)束");  //此處不會被執(zhí)行
}

//拋出的異常 Unhandled exception: 400

捕獲異常

捕獲異常的目的在于組織異常的傳播,并進(jìn)行一定的處理措施??梢詫⒂锌赡馨l(fā)生異常的代碼放在 try 代碼塊中并使用 catch 捕獲。如果需要捕獲的異常不止一種,可以使用多個 catch ?;拘问饺缦拢?/p>

main(){
  try{
    throw "拋出一個字符串提示異常";
  }on RangeError catch(e) {  
    // print(e);
  }on String catch(e) {
    print("字符串異常");
  }catch(e, s) {  //e為異常信息,s為異常的棧跟蹤信息
    print("其他異常:$e");
    print("棧信息:$s");
  }
}

上面代碼主動拋出一個異常,是一句字符串的提示信息,所以下面將執(zhí)行 print("字符串異常") ,on 后接一個異常的具體類型,因為我們拋出的是字符串異常信息,所以會進(jìn)入 on String catch(e) ,當(dāng)然可以定義其他具體異常類型。如果捕獲的異常并非 on 后接的異常類型,則進(jìn)入最后的未定義具體類型的異常。catch 方法可以有一個參數(shù)參數(shù)或兩個參數(shù),一個參數(shù)時,參數(shù)為異常提示信息,兩個參數(shù)時,第一個參數(shù)為異常提示信息,第二個為異常的堆棧信息(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 類型都不對,進(jìn)入最后的 catch 。

即使捕獲到了異常,開發(fā)者也可以根據(jù)具體情況決定是處理、忽略還是繼續(xù)拋出異常,如果需要繼續(xù)拋出,可使用 rethrow 關(guān)鍵字。 rethrow 允許部分處理異常或直接繼續(xù)拋出異常給其他方法處理。

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("善后處理或拋出異常后需要繼續(xù)執(zhí)行的代碼");
  }
}

此外有時需要無論是否拋出異常都執(zhí)行指定的代碼,則需要使用到 finally 關(guān)鍵字,如下:

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("善后處理或拋出異常后需要繼續(xù)執(zhí)行的代碼");
  }
}

四、斷言

Dart 中使用 assert 來調(diào)試程序的執(zhí)行,使用 assert 如果布爾條件為假,則中斷正常執(zhí)行,并拋出異常。assert 中的條件是任何可以轉(zhuǎn)化為布爾類型的對象,即使函數(shù)也可以。

main(){
  print("執(zhí)行第一步"); //輸出 執(zhí)行第一步
  assert(1 == 1);    //條件為真,繼續(xù)執(zhí)行
  print("執(zhí)行第二步"); //輸出 執(zhí)行第二步
  assert(1 == 2);    //條件為假,拋出異常
  print("執(zhí)行第三步"); //不執(zhí)行此處
}

//以上會拋出如下異常:
//執(zhí)行第一步
//執(zhí)行第二步
//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("不會執(zhí)行");
}

assert 可以有兩個參數(shù),第一個為任意可以解析為布爾值的表達(dá)式,第二個為附加說明信息。

在生產(chǎn)代碼中,assert 將被忽略,并且不會評估斷言的參數(shù)。

PS:如果您使用的是 VSCode 來運行 以上斷言代碼,如果安裝有 Code Runner 插件并使用此插件來運行代碼,則斷言不會執(zhí)行,需要通過 Debug -> Start Debugging 或 Debug -> Start Without Debugging 來運行代碼才會執(zhí)行斷言代碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內(nèi)容