1 变量与常量
1.1 声明变量
java当中声明变量我们再熟悉不过了比如int i = 0; String s = "hello";那么dart中也可以用这种方式来声明一个变量,但是还有其他两种。
// dart中和java一样的部分
int i ;
int j = 0;
String s = "echo";
Object obj1 = "hello";
Object obj2= 1;
// 使用var关键字
var int i = 0;
// 或者省去int也是可以的 dart会根据值去推导出 i 是什么类型的数据
var i = 1;
var str = "echo";
// 使用dynamic关键字
dynamic i = 0;
dynamic s= "echo";
(如果输出上面的代码会看到输出 i 的时候为null,而在java中int类型没有赋值则会默认等于0,由此可以推测dart语言中一切皆对象)
可以看到相比java多了两个关键字var和dynamic。其中var和JavaScript中类似,是一种弱类型的关键字。在声明变量赋值的那一刻便确定了是什么类型。这么说可能不是很好理解,下面看一下代码:
var i = 1;
i = "echo"; // 这样是不允许的
var j;
j = 10;
j = "jack"; // 这样是允许的
通过例子可以看到在声明 i 的时候直接赋值了一个整数类型 1 的值,那么 i 的类型就确定了,就是int,不能再赋予其他类型。但是只是声明了一个 j 的情况下,j 的类型是可以改变的。这种用法类似于Object。在dart中和java一样Object都是所有类的父类。可以理解为在声明变量的时候没有赋值,就相当于声明了一个Object类型的数据放在那里了。
而dynamic关键字声明的变量可以在运行时来动态确定具体类型。有些类似于java的反射原理。推荐不要经常使用。因为动态处理的肯定没有静态的效率高,就像反射一样会存在性能损耗。原则上这三种方式声明的数据对于完成业务需求没有什么太大的分别。
1.2 声明常量
我们都知道在java中我们可以通过final关键字来声明一个常量,那么在dart中同样可以使用final。不同的是dart中还多了一个关键字const,同样可以来声明常量。
final int i = 0; // 和java用法一样
i = i + 1; // 不允许
const j = 0;
j = j+1; //同样不允许
既然用法类似,那么为什么dart还要多搞出一个const来呢?这是因为final是在运行时常量,而const时编译时常量。这一点可以通过代码来直观的感受一下:
final int a = 1;
const int b = 2;
const int c = a ; //不允许
const int c = b + 1; // 允许
final d = b; // 允许
因为c需要在编译时就确定 而a是在运行的时候才确定,时间周期不同,所以是不可以的。d则是因为b已经在编译时确定了,那么到了运行的时候就自然可以使用了。
2 内置类型
我们都知道在java中有char,byte,short,int,long,float,double,boolean八大基本数据类型,它们都是关键字来实现的,而不是具体的类。在dart中没有基本类型,而是称之为"内置类型",总共有七种:
2.1 数值类型 num
在dart中只有int 和 double两种数值类型,而且它们都是具体的类,都派生子num类。这也就解释了在介绍变量的时候声明的int如果没有赋值的化会输出null。在语法方面和java中的没有什么区别。需要注意的是dart当中的int可以当作java当中的short,int,long来使用 如果我们编写的代码超过了4个字节,dart则会将其编译成类似java当中的long来使用,如果小于4个字节,则编译成java中的short或int。double类似。
2.2 字符类型 String
dart当中的String在使用上和java没什么区别,java支持的,dart同样支持。不用的是dart可以使用单引号来声明一个字符串:
String str1 = "echo"; // 和java一样
String str2 = 'hello'; // 单引号
在java中我们拼接字符串的时候通常是简单粗暴的使用 + 号,更好的使用StringBuffer或StringBuilder或者String.fomat();但是在dart中则是使用$符,和kotlin一样。
String s = "hello";
String s1 = s + "world"; // 输出 helloword
String s2 = "$s你好"; // 输出 hello你好
String s3 = "${s}1world"; // 输出 hello1world
都知道在java中如果需要输出一个"hello"这样带引号的字符串我们需要转译,但是在dart中输出带引号的字符串就变得容易多了:
String s = "\"hello\""; // java的方式 dart同样支持
String s1 = "'world'"; // 双引号中间套单引号
String s2 = '"你好"'; // 单引号中间套双引号
java中输出\n这样的字符串同样需要转译,dart则也有更优雅的方式:
String s = "\\n"; // java方式
String s1 = r"\n"; // dart方式
最后dart还支持""" """三引号的方式,作用是可以换行:
String s = """ aaaaa
bbbbb
cccccc""";
2.3 布尔类型 bool
布尔类型则和java是一样的,只是定义的方式不一样:
bool a = false;
2.4 数组类型 list
在java当中list我们称之为集合,但是在dart中则称为数组。本质上没什么太大区别,只是叫法不一样。下面是使用方法:
List<String> list = new List(); // 可以有泛型 但不再是熟悉的new ArrayList()了 也可以不用new关键字
List<String> strs = List();
List<int> list1 = [1,2,3,4,5]; // 可以在初始化的时候直接赋值 java是做不到这样的
int first = list1[0]; // 像数组一样通过下表取元素 但是么有get()方法
// 遍历数组
for(var o in list1){ // 类似java的foreach 但是和kotlin一样
var item = o;
}
for(int j = 0; j < list1.length; j++){ // 普通for循环
var item = list1[j];
}
另外需要注意的是如果使用const来修饰的话会有一些小的问题:
List list = const [1,2,3,4,5];
list.add(6);
list = [6,7,8];
这段代码在编译的时候是可以的,但是一运行就会报错。这是因为const修饰的是[1,2,3,4,5]这个对象。对象不可变了,那么添加就是不允许的。但是list这个引用可以引用其他的对象。
const List list = [1,2,3,4];
list = [5,6,7];
list.add(0);
const放在前面修饰的话上面这段代码是编译不过的。因为此时const修饰的是一个引用,而不是对象本身,那么引用本身就不可以在引用其他对象了。但是add操作同样也不允许。
也就是说不管const在哪,添加元素都是不被允许的。修饰对象则引用可以引用别的对象,修饰引用则引用不可引用其他对象。
2.5 映射集合 map
对应的就是java中的map,也是key-value的形式。区别就是在用法上面:
Map<String,int> map = {"1":1, "2":2, "3":3}
var value = map["1"]; // 根据key取value,key不存在时返回null
map["4"] = 4; // 添加一个新的元素
map["1"] = 100; // 修改key为"1"对应的value的值
// 遍历
var keys = map.keys; // 得到的 var keys的类型一个迭代器
var values = map.values; // 得到的 var values的类型一个迭代器
// 剩下的就和java的迭代器一样使用就可以了
如果用const修饰的话和list的表现一致,这里就不再赘述。
2.6 Unicode runes
这种类型在java中是没有的。Runes可以认为是特殊字符表示类。为了能够满足Unicode32的特殊字符的表示。Unicode就是一种编码标准,包括utf-8,utf-16,utf-32。Unicode32可以表示任意一个字符。java中的String就是一个表示Unicode16的字符的类。而Unicode32需要32位来表现字符,例如很多的特殊字符。具体可以参考# 深入学习Java中的字符串,代码点和代码单元这篇文章。
2.7 标识符 Symbols
类似于java中的常量。
var symb = #A;
print(symb);

硬要说具体的使用场景的话,可以用在switch-case当中😂。
3 操作符
3.1 类型判断操作符 as
在java当中我们经常会碰到强制类型转换,但是在dart中是不支持java那一套写法的。具体用法和kotlin一样,使用 as 关键字
num j = 0;
int k = num as int;
在java中我们经常使用a instanceof b来判断 a属不属于b类型,同样的dart也不支持这样做,取而代之的是用 is 来判断,和kotlin一样。
Object obj = 1;
if(obj is int){
}
if(obj !is int){ // 取反
}
3.2 赋值操作符 ??=
String str;
if(str == null){
str = "echo";
}
在java中我们经常这样使用来确保str有值。但是在dart中我们可以使用 ??= 来赋值:
String str;
if(str == null){
str = "echo";
}
str ??= "hello";
print(str)
最后的输出结果是echo,而不是我们以为的hello。??= 的真正意义是如果str为null那么进行赋值,如果不为null,那么就当这句代码不存在。也就是说如果没有上面的str == null这个if给str赋值的话,最后输出的结果就回事hello。
3.3 条件表达式 ??
dart除了支持我们在java中经常用的三目表达式,同时也可以使用 ?? 来进行条件判断:
String s;
String result = s ?? "echo";
最后输出结果为echo。?? 的具体用法就是如果 ?? 前面不为null就返回前面的内容,反之返回后面的内容。也就是说如果在声明的s的时候赋值了hello,那么最后就会输出hello。
3.4 级联操作符 ..
在java中我们经常使用Builder设计模式,但是每个方法我们都必须返回Builder本身,也就是return this才可以进行链式调用。那么在dart中我们就可以中 .. 级联操作符来实现不用返回本身也可以实现链式调用:
class Builder{
void name(){
}
void age(){
}
}
// 使用
new Builder()..name()..age();
可以看到即使返回值是void也可以使用。
3.5 安全操作符 ?.
java中经常会出现空指针异常,相信都有遇到过。那么在dart里就使用了 ?. 来避免空指针,和kotlin的空安全是一样的:
String str;
print(str?.length);
str字符串没有赋值,使用了 ?. 之后会打印null,而不是抛出空指针异常。
关于dart的变量,常量,操作符的基本入门学习就到此结束了。。。
网友评论