笔者也是刚刚接触dart的学习,毕竟作为一门出现比Java更晚的语言,感觉相比java还是有很多人性化的地方。现在就以和大家熟悉的java对比的角度,分享一下dart中和java不同的地方。

一、变量

我们知道在Java中声明变量的时候一定要给予类型,但是在dart中可以不指定类型,进而使用Object、var、dynamic来代替,下面笔者带大家一一过一下。

Object:其中Object代表所有对象,这个和java没什么区别,故而Object可以用来声明所有类型的变量,当然也包括int。这里需要注意的是,在dart中int也是一个类,而不是关键字了,可以在AS中点进去查看int类信息。进而我们get到dart并不是完全按照驼峰规则来编写的,比如int是一个类,在驼峰规则中首字母本应该大写,但是却没有。

var:其实在很多语言中都有var的用法,比如js、kotlin等。在dart中,var声明的变量在声明时已经决定了类型,后面不能更改,如果更改ide将会直接报错。但是如果在声明时没有赋值,而是后面赋值的话,该变量类型是可以修改的。


dynamic:在运行时动态修改变量类型,可以随意赋值任何类型。但是根据笔者经验,一般运行时修改的效率都会更低一些,比如反射。所以不优先使用dynamic,后面碰到有坑再说。

final和const修饰符:使用final和const修饰符都可以将变量修饰成不可变,区别在于final是运行时赋值,但是const是在编译时就已经赋值,所以如果将一个final变量赋值给const变量是会报错的,因为const需要在编译时给定值,但是此时final的变量并没有真正赋值。反之const赋值给final则可以,const赋值给cost、final赋值给final均可以。

二、数据类型

在java中,拥有八大数据类型,相信大家都知道,这里就不一一举例了,在dart中那八大数据类型也是支持的,只是说从java中数据类型是关键字变成了类而已,并且取消了包装类机制,和java使用起来一模一样。值得一提的是,在dart中新增了一些数据类型,接下来一一说明。

num:前面说过,在dart中数据类型也是类,比如int虽然首字母小写但是它依然是一个类。num也是一样,num有2个子类,分别是int和double。需要注意的是在dart中没有float这个数据类型,只有double。总结来说就是,如果一个数字既可能是整型又可能是浮点型的话,可以定义为num的对象。如果想让double转int可以使用doubleValue.toInt()方法,注意如果在计算时double/double表示返回一个double,但是使用double~/double来表示返回整数。

String:在dart中String可以用单引号、双引号、三引号包起来,单双引号作用类似,但是可以配合起来使用,解决在双引号中包含特殊字符的问题,比如如果一个变量是a"b",如果在java中表示该字符串,需要写成"a\"b\"",但是利用单双引号配合,则可以简写成'a"b"'或者"a'b'"即可。三引号代表可以换行的字符串,可以直接在内容中间回车。

List:和java中的数组类似,也可以初始化的时候直接赋值,比如List<int> lists = [1,2,3,3],下标也是从0开始,比如修改第一个元素的值为2可以写成lists[0]=2。可以用const关键字来修饰,代表该list不可变。const List = XX和List = const XX这两种写法都可以。遍历的话和java类似,也可以用for循环和foreach循环。for(int i in lists)、lists.foreach((e)=>{print(e)})。

map:在dart中map键值对支持在初始化的时候赋值,类似于这样,map m ={ 'a': '阿里巴巴', 't': '腾讯', 'b': '百度'},获取值也是根据key来获取value,类似于var valuea = m['a']。遍历的话仍然是迭代器,和java中一样。

三、操作符

java中常见操作符在dart中依然可用,这里说一说dart新增的操作符

1.类型判定操作符

as:类似于java中的强制转换,将A类型的数据强制转换成B类型,若无法转换则抛出异常

is:判断某个对象是否属于某个类,相当于java中的instanceof关键字

is!:和is相反,如果某个对象属于某个类,则返回false

2.赋值操作符

??=:跟在一个变量后面,如果该变量值不为null则保持不变,如果为null则赋值成另外的值。举个例子,b ??= value,如果b为null则不管,不为null则将b赋值成value

3.条件表达式

expr1 ?? expr2:如果expr1不为null,则返回其值,否则返回expr2的值

4.级联操作符

..:级联操作符可以在同一个对象上 连续调用多个函数以及访问成员变量。 使用级联操作符可以避免创建临时变量, 并且写出来的代码看起来更加流畅,相当于dart系统自带build模式

5.安全操作符

?.:如果该操作符前面的变量为null则返回null不调用后面的方法或属性,可以避免空指针。比如print(a?.length),如果不用安全操作符还需要判断a是否为null,否则万一为null会报空指针

四、方法

dart中方法也有很多有趣的地方,很多都是借鉴的其他语言优点。这里就以java作为对比,列举一下dart中新特性。

特性一  方式实现可简写

当方法中只有一个表达式时,可以不使用大括号包住实现,而是使用等号箭头。注意,这里的参数类型已经省略,返回值void其实也可省略,只是不推荐这么做,省略号将变成dynamic。


特性二  一等方法对象

在dart中方法也是对象,方法的父类为Function类,这意味着方法可以赋值为变量,也意味着方法也可以作为参数传递其他方法中。


特性二  可选位置参数

把方法的参数放到[ ]中,代表参数可传可不传,传值时按照参数位置顺序传递 。如下定义了一个func方法,将i和j作为可选位置参数,最后调用时只传了1个。根据可选位置参数的特性,当参数只传了一个时,固定传给第一个参数,最后打出的结果是i为1,j为null。注意,当传的参数类型和方法第一个参数不一致时,比如讲参数1换成字符串,将直接报错。

特性三  可选命名参数

把方法的参数放到{ }中,代表参数必须通过指定形参名进行传参。如下图,通过形参:值进行传值,也可以只传其中一部分,但是必须执行给谁传值了。


特性四  默认参数值

使用[ ]或者{ }方式定义方法中的参数时,可以给定默认值。如下,在定义方法func时,我们给定了i和j分别一个默认值,在它们没传值时默认为0。


特性五  匿名方法

dart也支持匿名方法,也可以称之为 lambda 或者 closure 闭包 ,可以作为传参用。如下例,在调用方法时将一个匿名方法传入另一方法test中,接下来在test方法调用参数f自身。

五、异常

和 Java 不同的是,所有的 Dart 异常是非检查异常。 方法不一定声明了他们所抛出的异常, 并且不要求你捕获任何异常。 另外,Dart 提供了 ExceptionError 类型, 以及一些子类型。你还可以定义自己的异常类型。但是, Dart 代码可以抛出任何非 null 对象为异常,不仅仅是实现了 Exception 或者Error 的对象。 如下图,我们抛出了一个整数异常,将在try...catch中的on int catch(e){}中被捕获。这是和java不一样的地方,java只能抛出Exception子类。


在java中,通过catch到的Exception类型来区分Exception作相应处理。在dart中通过on 任意对象类的方式来抓住错误,该对象即为throw的对象,这里可以使用rethrow将捕获的异常重新抛出。同时catch中参数e是抛出的异常对象,可以通过e.runtimeType来查看实际的类,s是错误堆栈。dart中try...catch也是有finally的,finally和Java一样在try catch执行完后执行。


总结:本次以java作为对比,介绍了一下dart中的亮点新玩法,里面肯定有没有列全的,请大家多担待,因为笔者也是刚接触dart,后面有新的发现会继续学习然后给大家分享。当然有很多方面没有跟大家说到,没说到的部分就默认和java一样,大家可以自己尝试去亲身体验一把。总而言之,我们可以发现,dart确实是一门很简洁的语言,有很多地方都可以省略,比如变量类型、方法类型、单表达式的方法体括号等等。同时,又有很多的优化,只要在判空和赋值方面,具体见上面的操作符部分。然后,还有很多的新鲜玩法,比如支持匿名方法、可以将任何类作为异常捕获对象、在java中熟知的int等基本数据类型也变成了类。我相信肯定还有更多的好玩点等着我们去学习发现,笔者后面学习到了再继续分享出来。