Dart语言(一)--基础语法

一、Dart基本特色概念

  1. 所有变量的值都是对象,也就是类的实例。数字函数null也都是对象,都继承自Object类。
  2. 虽然Dart是强类型语言,但Dart支持类型推断,显示变量类型声明是可选的。没有指定类型的变量的类型为dynamic。可以通过使用类型或者编译时常量来帮助Dart去捕获异常以及让代码运行更高效。
  3. Dart支持泛型List<int>表示包含int类型的列表,List<dynamic>则表示包含任意类型的列表。(List<dynamic>等同于List)
  4. Dart支持顶层(Top-level)函数(例如:main()),也支持类中定义函数(静态函数和实例函数),也支持嵌套函数和本地函数。
  5. Dart支持顶层变量和类成员变量。
  6. Dart没有publicprotectedprivate这些关键字,使用下划线_开头的变量或函数,表示库内可见。

二、语法预览

//程序入口函数
main() {
  //42,字面量,编译时常量
  var number = 42; // 定义的一个变量,dynamic
  printNumber(number);
  print('number ${number.runtimeType}'); //打印number的运行时类型
}

printNumber(num number) {
  print('The number is $number');
//  return null;如果函数没有返回值,此处默认返回null
}

//打印结果
The number is 42
number int
  1. 所有的函数都返回一个值。如果没有指定返回值,则默认把return null作为函数的最后一个语句执行。

  2. main()方法是Dart程序执行的入口方法,每个程序都需要一个这样的方法。

    • main()方法签名的void可有可无。

    • main()方法有一个可选的List<String>参数,此参数在Android studio运行时配置,如图:
      在这里插入图片描述在这里插入图片描述

  3. var一种不指定类型声明变量的方式。

    • Dart中一切皆对象,所以没有初始化的默认值都是nullnullNull类的唯一实例。
    • 我们也可以给变量申请一个具体类型,这样有助于编译工具帮我们补全代码,查找bug。如:String name = 'Bob';
    • 在代码风格中,推荐在编写严格API时尽量使用类型声明(规定使用),编写独立应用时尽量使用var声明(快速开发)。
    • 想要知道具体类型,使用runtimeType
  4. var number = 42;中42 是一个字面量。字面量是编译时常量。

  5. num是一个类型(类型接口,子类有intdouble)。

  6. print()是打印语句,参数可以是a+b,a,” “,’ '都行。

三、内置类型

Numbers(数值)

  1. intdouble都是数值类型,都是num的子类。
    • int是整数型,取值范围在-2^53 和 2^53 之间。1, 2,3 ,4 …
    • double是浮点型 , 64位。1.2324, …
  2. num类型定义了基本的操作符,例如+ ,- , *, / ,= ,<=等等,还定义了abs()ceil()floor()等函数。
int i = 1;
double d = 1.2;
num j = 1;
num k = 1.2;

String字符串

  1. 字符串可以使用双引号" ",单引号’ ‘或三个单引号’’’ ‘’’。

    • 双引号和单引号都是定义单行的字符串
    • 三个单引号连用的可以定义多行的字符串类型
    • Dart 的String 是 UTF-16 编码的一个队列。
    String str1 = 'abc';//单引号字符串
    String str2 = "abc";//双引号字符串
    //三个', ' 或 " (不能混合使用)来定义多行的String类型,注意str3和str4的显示区别
    String str3 = '''abc
          def''';
    String str4 = "abc"
      "def";
    String str5 = "abc"+"def";//str4和str5是一样的
    print("str1 = $str1");//abc
    print("str2 = $str2");//abc
    print("str3 = $str3");//abc \n def  此处是两行  中间的回车和空格也被打印出来了
    print("str4 = $str4");//abcdef  此处忽略了回车和空格
    print("str5 = $str5");//abcdef
    
  2. r前缀是忽略转义符,创建一个”原始raw“的字符串。可以打印完整的url。

//通过提供一个r前缀可以创建一个 “原始 raw” 字符串,原始字符串中没转义字符
var s = r"In a raw string, even \n isn't special."
print("s = $s");
//打印结果:In a raw string, even \n isn't special.
  1. 字符串与数值之间的转换
// String -> int
var one = int.parse('1');
// String -> double
var onePointOne = double.parse('1.1');
// int -> String
String oneAsString = 1.toString();
// double -> String
//此处是小数点后保留两位,四舍五入
String piAsString = 3.14159.toStringAsFixed(2);
piAsString = '3.14';

Boolean(布尔值)

  1. 只有true和false两个值,但只有true对象还被认为是true。
  2. 使用bool的类型
bool flagTrue = true ;
bool flagFalse = false ;
if(1){}//错误不可这么写
if(1 != 0){}
if(true){}
if(false){}

Lists(列表)

  1. List中可指定类型,如List<int>List<String>等,也可不指定类型,此时默认为任意型,可混合保存
  2. List可以直接定义一个具体的类别,也可以new一个实例,然后添加。
  3. 其中的元素可以使用runtimeType查看运行时的类型。
  4. List类中提供各种API,类似java中的list。
  5. 遍历元素 使用forEach(void f(E element))
//直接定义int类型的列表
List<int> list1 = [1, 2, 3];
//直接定义String类型的列表
List<String> list2 = ['a', 'b', 'c'];
//直接定义可存放任意类型的列表
var list3 = [1, 'a', 3];
//new出list实例,可添加元素
var list4 = new List();
list4.add(4);
list4.add("dart");
list4.add(6);

//列表中一些常用方法
list1.[1];//2
list2.length;//3
[].length;//0
[].isEmpty;//true
['a'].isEmpty;//false

print('list1 = $list1');//list1 = [1, 2, 3]
print('list2 = $list2');//list2 = [a, b, c]
print('list3 = $list3');//list3 = [1, a, 3]
print('list4 = $list4');//list4 = [4, dart, 6]
print('${list3[0].runtimeType},${list3[1].runtimeType}');//int,String
//runtimeType,返回(运行时类型)对象的类型

//遍历元素  使用forEach(void f(E element))
 list4.forEach((a){
    print(a);
  });
//打印结果
4
dart
6

map

  1. map是键值对形式的集合。键可以是任意类型。
  2. 遍历元素 使用forEach(void f(K key, V value))
//直接定义
// Keys  : Values
var colors1 = {
  'first' : 'red',
  12: 'green',
  'third' : 'blue'
};
print('colors1 = $colors1');//colors1 = {first: red, 12: green, third: blue}
print(colors1[12]);//green

var colors2 = new Map();
//中括号内为key,等号右为值
colors2['first'] = 'red';
colors2['second'] = 'green';
colors2['third'] = 'blue';

//通过map中的key获取value,如果所查找的key不存在,则返回 null:
print('colors2['first']=${colors2['first']}');//'colors2['first']=red
//获取长度
print('colors2.length = ${colors2.length}');//colors2.length = 3

//遍历元素
colors2.forEach((key,value){
    print('key = $key;value = $value');
  });

//打印结果
key = first;value = red
key = second;value = green
key = third;value = blue

Runes符号文字 (不常用)

  1. Dart语言中String字符串是一系列UTF-16代码单元,Sting的codeUnitscodeUnitAt属性可以获取UTF-16字符集的字符。
  2. 通常使用 \uXXXX 的方式来表示 Unicode code point,这里的 XXXX 是4个 16 进制的数。例如,心形符号 (♥) 是 \u2665。对于非 4 个数值的情况,把编码值放到大括号中即可。例如,笑脸 emoji (?) 是 \u{1f600}。
  3. 如果String字符串中需要表示32位Unicode值需要使用runes来获取UTF-32的字符集的字符。
  4. runes代表字符串的 UTF-32 code points。
  var clapping = '\u{1f44f}';
  print(clapping);
  print(clapping.codeUnits);//16-bit
  print(clapping.codeUnitAt(1));
  print(clapping.runes.toList());//32-bit

  Runes input = new Runes(
      '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
  print(new String.fromCharCodes(input));

//打印结果
?
[55357, 56399]
56399
[128079]
♥  ?  ?  ?  ?  ?

注意:
使用 list 操作 runes 的时候请小心。根据所操作的语种、字符集等,这种操作方式可能导致你的字符串出问题。

Symbols标志(基本用不上)

一个 Symbol object 代表 Dart 程序中声明的操作符或者标识符。 你也许从来不会用到 Symbol,但是该功能对于通过名字来引用标识符的情况 是非常有价值的,特别是混淆后的代码, 标识符的名字被混淆了,但是 Symbol 的名字不会改变。

使用 Symbol 字面量来获取标识符的 symbol 对象,也就是在标识符 前面添加一个 # 符号:

#radix
#bar

Symbol 字面量定义是编译时常量。

四、Functions(方法)

1、基本特点

  1. Dart中方法也是一个对象,类型为Function
  2. 方法可以赋值给变量,也可以当做其他方法的参数,也可把Dart类的实例当做方法来调用。
  3. 方法有返回值,如果没有指定返回值,默认将return null;作为最后语句返回null。
  4. main()方法是程序的入口方法。
  5. Dart中没有final方法,几乎所有方法都允许重写(部分内置的操作符除外)
  6. 当方法只有一个表达式时,可以使用 => 缩写。
  7. 方法中的返回类型和参数类型可以省略。
//平时使用方式
String sayHello1(String name){
  return 'Hello $name!';
  //return print('Hello $name!');//print();方法返回的是void
}

//这样也是可以的,忽略类型定义
sayHello2(name){
  return 'Hello $name!';
}

//对于只有一个表达式的方法,你可以选择使用缩写语法来定义:
sayHello3(name) => 'Hello $name!';
//注意:在箭头 (=>) 和冒号 (;) 之间只能使用一个表达式 –- 不能使用语句。 表达式计算后通常会返回一个单独的值.
//例如下面这些,注释后面的就是表达式:
int i = 10;//i = 10
anArray[0] = 10;//anArray[0] = 100
int result = 1 + 2; // result = 1 + 2
if (value1 == value2)//value1 == value2

//方法也可以赋值给一个变量--类似函数指针
var sayHello4 = (name)=>'Hello $name!';

2、函数闭包

一个 闭包 是一个方法对象,不管该对象在何处被调用, 该对象都可以访问其作用域内 的变量。

方法可以封闭定义到其作用域内的变量。 下面的示例中,makeAdder() 捕获到了变量 addBy。 不管你在那里执行 makeAdder() 所返回的函数,都可以使用 addBy 参数。

//返回值为Function
Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}

main() {
  //方法可以赋值给变量,
  //此时将makeAdder的返回值(num i) => addBy + i 赋值给add2和add4
  var add2 = makeAdder(2);//此时add2是个方法,等价于add2(num i) => 2 + i;
  var add4 = makeAdder(4);//此时add4是个方法,等价于add4(num i) => 4 + i;
	
  //断言 判断内容是否正确,错误会抛出异常
  assert(add2(3) == 5);//add2(3)=5
  assert(add4(3) == 7);//add4(3)=7
}

3、typedef 别名

  1. typedef 是方法的简单的别名,它提供了一种方法来检查任何函数的类型。
  2. typedef定义的别名方法有返回值,那么定义的方法不仅要参数匹配,返回值也要一样,否则或报错。
  3. typedef定义的别名方法没有返回值,那么只要参数匹配就可以了。
  4. 定义typedef的别名方法也可以使用泛型。
typedef int Compare(int a, int b);
typedef Fun1(int a, int b);
typedef Fun<T, K>(T a, K b);

int sort(int a, int b) => a - b;

main() {
  assert(sort is Compare); // True!
}
typedef int Compare(int a, int b);
typedef Fun1(int a, int b);
typedef Fun2<T, K>(T a, K b);

int add(int a, int b) {
  print('a * b');
  return a * b;
}

 add1(int a, int b) {
  print('a + b');
  return a + b;
}

 add2(String a, int b) {
    print('a = b');
  	return 'a = ' + b.toString();
}

class Demo1 {
  Demo1(int f(int a, int b), int x, int y) {
    var sum = f(x, y);
    print("sum1 : $sum");
  }
}

class Demo2 {
  Demo2(Fun1 f, int x, int y) {
    var sum = f(x, y);
    print("sum2 : $sum");
  }
}

class Demo3 {
  Demo3(Fun2<String, int> f, String x, int y) {
    var sum = f(x, y);
    print("sum3 : $sum");
  }
}

goTypedef() {
  Demo1 d1 = new Demo1(add, 2, 3);
  Demo2 d2 = new Demo2(add1, 5, 6);
  Demo3 d3 = new Demo3(add2, 'a', 6);
}

main() {
  goTypedef();
}
//打印结果
a * b
sum1 : 6
a + b
sum2 : 11
a = b   
sum3 : a = 6

目前,typedef 只能使用在 function 类型上。

4、可选参数的方法

  1. 可选参数可分为:可选命名的和可选位置的
  2. 方法中参数可以有默认值。赋默认值的方式两种:等号’=‘或者冒号’:’,默认值至少编译时常量。

a、可选命名参数

  1. 在定义时,使用大括号内加参数{paramName param1,param2...}的形式定义参数,类型可有可无。
  2. 在调用时,使用paramName : value来指定命名参数。可指定任意参数,没有顺序要求。
//定义可选命名参数的方法
//赋默认值的方式两种:等号'='或者冒号':',
FunA(bool a, {b, c:3, d=4, e}){
	print('a = $a,b = $b,c = $c,d = $d,e = $e');
}

void main(){
  	//调用
	FunA(true,b:2,e:5);
	FunA(false,b:"one",c:5,);
}

//打印结果
a = true,b = 2,c = 3,d = 4,e = 5
a = false,b = one,c = 5,d = 4,e = null

b、可选位置参数

  1. 在定义时,使用中括号内加参数[paramName param1,param2…]`的形式定义参数,类型可以有可无。
  2. 在调用时,直接传入参数就行,但是参数位置是按顺序赋值的,如果要给最后一个参数传值,前面的参数也要传值。
//定义可选位置
//赋默认值只有一种方式:等号'='
FunB(a, [b, c=3, d=4, e]){
	 print('a = $a,b = $b,c = $c,d = $d,e = $e');
}
//调用
main() {
	FunB(true,2, 5);
    FunB(false,"one",5,6,7);
}
//打印结果
a = true,b = 2,c = 5,d = 4,e = null
a = false,b = one,c = 5,d = 6,e = 7

c、以List,map作为默认参数

void doStuff(
    {List<int> list = const [1, 2, 3],
    Map<String, String> gifts = const {
      'first': 'paper',
      'second': 'cotton',
      'third': 'leather'
    }}) {

  print('list:  $list');
  print('gifts: $gifts');
}

main() {
  doStuff();
}

//打印结果
list:  [1, 2, 3]
gifts: {first: paper, second: cotton, third: leather}

5、方法可作为参数被调用

//定义一个普通方法
printNumber(name) {
  print(name);
}

main() {
    var list = [1, 2, 3];
	//可以把方法当做参数调用另外一个方法
    list.forEach(printNumber);

	//匿名方法
	list.forEach((i){
 	   print(i);
	});
}
//打印结果都是
	1
    2
    3

五、操作符

1、Dart中定义的操作符

下表为Dart中定义的操作符,很多操作符是可以重载的。

描述操作符解释
unary postfix
一元后缀
expr++ 自增 expr--自减 () 调用方法 [] 访问列表元素
. 访问元素 ?.条件非空判断
用在表达式后
unary prefix
一元前缀
-expr负号 !expr 取反 ~expr 补码 ++expr 自增 --expr自减用在表达式前
基本运算符+-*/ 除,除不尽就显示小数
% 取模 ~/除后取z整
~/与java中/效果一样,其余与java中操作符运算一样
Bitwise and shift operators
(位和移位操作符)
<< 左移 >> 右移 &位与 | 位或 ^位异或与java中操作符运算一样
Equality and relational operators
(相等相关的操作符)
>= 大于等于 > 大于 <= 小于等于 < 小于 == 等于 != 不等于与java中操作符运算一样
Assignment operators
(赋值操作符)
= 直接赋值 *= 乘后赋值 >>=右移后赋值
~/= 取余后赋值 %= 取模后赋值 += 加后赋值
-= 减后赋值 <<= 左移后赋值/= 除后赋值
&= 位与后赋值 ^= 异或后赋值 |= 位或后赋值 ??=非空判断后赋值,
??=java中没有,Dart中特有的
Type test operators
(类型判定操作符)
asisis!都是java中没有,Dart中特有的
Logical operators
(逻辑操作符)
!expr取反 || 逻辑或 &&逻辑与与java中操作符运算一样
if null 如果空判断??效果与三目表达式一样
conditional 三目expr1 ? expr2 : expr3与java中操作符运算一样
Cascade notation
(级联操作符)
..java中没有,Dart中特有的

2、Dart中特有的操作符

(1)as,is,is! 类型判断操作符

操作符解释
as类型转换 (把左边对象转换为右边特定的类型)
is如果对象是指定的类型返回 True(检查is左边的类型是否是右边的类型)
is!如果对象是指定的类型返回 False(检查is左边的类型是否是右边的类型)
  1. 使用isis!时,只有obj实现了T的接口,obj is T才是true
  2. 使用as时,如果左边obj未实现右边T,则使用obj as T会抛异常。所以在使用as时要先使用is判断类型。
if (emp is Person) { // Type check,如果emp不是Person子类,是false,就不会跳进
  emp.firstName = 'Bob';
}
//如果emp为null不是Person类型,则(emp as Person)就会抛出异常
(emp as Person).firstName = 'Bob';
//建议这样书写
if(emp is Person){
    (emp as Person).firstName = 'Bob';
}

(2) ??=

??= 操作符用来指定值为 null 的变量的值。

main() {
  var b;
  b = 2; //给 b 变量赋值
  print('给b赋值后 b = $b');
  b ??= 1; // 如果 b 是 null,则将1赋值给 b;如果b不是 null,则 b 的值保持不变
  print('b ??= 1操作后 b = $b');
  b = null;
  print('将b置为null后 b = $b');
  b ??= 1;
  print('b ??= 1操作后 b = $b');
}
//打印结果
给b赋值后 b = 2
b ??= 1操作后 b = 2
将b置为null后 b = null
b ??= 1操作后 b = 1

(3)?? 效果类似三目运算

b ??= value; // 如果 b 是 null,则赋值给 b;如果不是 null,则 b 的值保持不变

String toString() => msg ?? super.toString();
//两个表达式效果相同
String toString() => msg == null ? super.toString() : msg;

(4)?.

.类似,但是左边的操作对象不能为 null,例如foo?.bar 如果 foo 为 null 则返回 null,否则返回 bar 成员

class A {
  var bar = 1;
}

main() {
  A foo;
  print('foo?.bar =${foo?.bar}');
  foo= A();
  print('foo?.bar =${foo?.bar}');
}
//打印结果
foo?.bar =null
foo?.bar =1

(5) ..级联语法

  1. 级联操作符 (..) 可以在同一个对象上连续调用多个函数以及访问成员变量。
  2. 使用级联操作符可以避免创建临时变量,并且写出来的代码看起来更加流畅:
  3. 在方法上使用级联操作符需要非常小心,无法在返回值为 void 上使用级联操作符

注意: 严格来说,两个点的级联语法不是一个操作符。只是一个 Dart 特殊语法。

class Person {
    String name;
    String country;
    void setCountry(String country){
      this.country = country;
    }
    String toString() => 'Name:$name\nCountry:$country';
}
void main() {
  Person p = new Person();
  p ..name = 'Wang'
    ..setCountry('China');
  print(p);
}
//打印结果:
Name:Wang
Country:China

六、控制语句

1、if and else 判断语句

  1. 与其他语言的if else使用方式一样。
  2. 在Dart语言中注意对true的定义,只有true对象才被定义为true。
if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}

2、for loops for循环

  1. 可以使用标准的for循环
for (var i = 0; i < 5; i++) {
 ......
}
  1. Dart中for循环的闭包可以自己捕获循环的index索引值。获取索引对应的值。
var letters = ["a",'b','c'];
letters.forEach((letter){
    print('letter = $letter');
  });
//打印结果
letter = a
letter = b
letter = c
  1. List 和 Set 等实现了 Iterable 接口的类还支持for-in形式的遍历。
List letters = ["a",'b','c'];
for(var letter in letters){
    print('letter = $letter');
  }
//打印结果
letter = a
letter = b
letter = c

3、while and do-while loops while循环

  1. while循环,先判断条件,为true进入循环,否则跳过。
int a = 1;
while(a < 5){
    print('a = $a');
    a++;
}
//打印结果
a = 1
a = 2
a = 3
a = 4
  1. do…while循环,先执行循环代码,然后再判断条件。即此循环至少能执行一次循环语句。
int b = 0;
do{
    b ++;
    print('b = $b');
}while(b < 0);
//打印结果
b = 1

4、break and continue 控制语句

  1. 使用break来终止循环
main() {
  var a = 0 ;
  while(true){
    print('a = $a');
    if(a > 2){
      print('a = $a 时终止循环');
      break;
    }
    a++;
  }
}
//打印结果
a = 0
a = 1
a = 2
a = 3
a = 3 时终止循环
  1. 使用 continue 来开始下一次循环:
main(){
	for (int i = 0; i < 4; i++) {
	   if(i ==2 ){
	     print('当i = $i时,跳过此处操作。');
	     continue;
	   }
	   print('i = $i');
	}
}
//打印结果
i = 0
i = 1
当i = 2时,跳过此处操作。
i = 3

5、switch case

  1. Dart中switch语句是通过==来和case后的intString或者编译时常量的。
  2. 每个非空的case语句都必须有一个break语句。另外也可以通过continuethrow或者return来结束非空的case语句。空的case语句可以省略break语句。
  3. 当没有case语句匹配的时候,可以使用default语句来匹配这种默认情况。
  4. case都必须是编译时常量,这些常量必须符合以下条件:
    • 都是int的实例
    • 都是String的实例
    • 都是同一个类的实例且该类必须从Object继承了==的实现
    • switch使用比较,class必须没有覆写操作符
  var flag = 1;
  switch (flag) {
    case 0:
   //   break;//当注释此处的break,则不会报错,此时flag=0时会继续往下执行 case 1的逻辑
    case 1:
      print('flag = $flag');
      break; //挡注释调此处break时,编译时会报错
    case 2:
      print('flag = $flag');
      break;
    default://此时flag没有匹配到case语句
      print('flag = $flag');
      break;
  }
  1. 当switch语句中使用枚举时,在case语句中要把枚举中每个值都写上,或者使用default,否则会报错。
enum Color { red, green, blue }
Color color = Color.red;
switch (color) {
  case Color.red:
    print("color.red");
  case Color.blue:
    print("color.blue");
    break;
 //当注释到以下内容,编译时会报错error: Missing case clause for 'green'. 
  //case Color.green:   
  //  print("color.green");
  //  break;
  //default:
}
  1. 在执行了一个case语句后,还想继续执行,可以使用continue语句跳到对应标签继续执行。
enum Color { red, green, blue }
main() {
  Color color = Color.red;
  switch (color) {
    case Color.red:
      print("color.red");
      continue goGreen;//定义一个标签,名字随意
    case Color.blue:
      print("color.blue");
      break;
    goGreen://此处标签要与continue对应
    case Color.green:
      print("color.green");
      break;
    default:
  }
}
//打印结果
color.red
color.green

6、assert 断言

  1. assert 方法的参数可以为任何返回布尔值的表达式或者方法。如果返回的值为 true,断言执行通过,执行结束。如果返回值为 false,断言执行失败,会抛出一个异常 AssertionError)。
  2. 如果条件表达式结果不满足需要,则可以使用 assert 语句俩打断代码的执行。
int lineCount;
assert(lineCount == null);//断言
//如果条件不为 true 则会抛出一个AssertionError异常。

七、异常Exceptions

  1. Dart中异常是非检查异常,方法不一定声明了他们所抛出的异常,并且不要钱捕获任何异常。
  2. 如果异常没有捕获,则异常会抛出,导致抛出异常的代码终止执行。
  3. Dart中throw可以抛出任意非null对象作为异常,不仅是提供的ExceptionError类型。
  4. 你可以使用on 或者 catch 来声明捕获语句,也可以同时使用。使用 on 来指定异常类型,使用 catch 来捕获异常对象。
  5. 使用rethrow 关键字可以 把捕获的异常给 重新抛出。
void goThrow(num a) {
  try {
    getName2(a);
    print('继续执行');
  } catch (e, s) {
    //函数 catch() 可以带有一个或者两个参数, 第一个参数为抛出的异常对象,
    // 第二个为堆栈信息 (一个 StackTrace 对象)。
    print("goThrow catch = $e\n$s");
  } finally {
    print('goThrow finally');
  }
}

getName2(num a) {
  //你可以使用on 或者 catch 来声明捕获语句,也可以同时使用。
  // 使用 on 来指定异常类型,使用 catch 来捕获异常对象。
  try {
    getName(a);
  } on Exception {
    print("getName2:Exception");
  } on NullThrownError catch (e) {
    print("getName2 on = $e");
    //使用 rethrow 关键字可以 把捕获的异常给 重新抛出。
    rethrow;
  } catch (e) {
    // 没指定类型,捕获任何异常类型
    print("getName2 catch $e");
  }
}

getName(num a) {
  if (a ==0) {
    throw new NullThrownError();
  }else if(a == 1){
    throw "不为0";
  }
  print('准备执行');
}

main() {
  goThrow(1);
  //goThrow(0);
  //goThrow(3);
}

//goThrow(1);打印结果
getName2 catch 不为0
继续执行
goThrow finally
    
//goThrow(0);打印结果
getName2 on = Throw of null.
goThrow catch = Throw of null.
#0      getName (file:///D:/project/flutter_app/lib/demo1.dart:36:5)
#1      getName2 (file:///D:/project/flutter_app/lib/demo1.dart:21:5)
#2      goThrow (file:///D:/project/flutter_app/lib/demo1.dart:6:5)
#3      main (file:///D:/project/flutter_app/lib/demo1.dart:44:3)
#4      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:289:19)
#5      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
              
goThrow finally
              
//goThrow(3);打印结果             
准备执行
继续执行
goThrow finally              
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值