编程语言最基本的特征之一就是它支持的数据类型。这些是可以用编程语言表示和操作的值的类型。Dart语言支持以下类型:
1、数字int、double
2、字符串String
3、布尔bool
4、列表(类似于数组)list
5、集合Set
6、映射Map
7、符文(用于表示字符串中的Unicode字符)
8、符号
Dart中的数字类型用于表示数字文字。Dart中的数字类型有两种类型:
1、整数int:整数值表示非小数值,即没有小数点的数值。整数值不大于64位, 具体取决于平台。 在 Dart VM 上, 值的范围从 -263 到 263 - 1。 Dart 被编译为 JavaScript 时,使用 JavaScript numbers, 值的范围从 -253 到 253 - 1。例如,10是整数。使用int关键字表示整数文字。
2、**双精度数double **:Dart还支持小数数值,即带小数点的值。Dart中的Double数据类型表示64位(双精度)浮点数。例如,10.10。关键字double用于表示浮点文字。
int 和 double 都是num的子类。 num 类型包括基本运算 +, -, /和*, 以及 abs(), ceil(), 和 floor()等函数方法。如果 num 及其子类找不到你想要的方法,尝试使用 dart:math 库。
整数是没有小数点的数字。以下是定义整数文字的一些示例:
var x = 123;
var hex = 0xDEADBEEF;
如果数字包含小数,则为双精度数。以下是定义双精度数文字的一些示例:
var y = 1.199;
var exponents = 1.42e5;
从Dart 2.1开始,必要时整数文字会自动转换为双精度数:
double z = 10; //相当于double z = 10.0
因此,看一个变量到底是整数还是双精度数,不是看他的值是否带小数点,而是要看声明他的关键字以及系统默认推导是什么,比如上面声明变量的关键字中,var x = 123被默认推导为整数;var y = 1.199被默认推到位小数;而double z = 10则是直接告诉系统告诉我们这个变量是一个双精度的小数,相当double z = 10.0。具体用法示例:
void dataSwitch(){
//String 转化为int
var strToInt = int.parse("1");
bool result = (strToInt == 1);
print("String 转化为int后的比较的结果:$result");
//String转化为double
double strToDouble = double.parse("1.3");
result = (strToDouble == 1.3000);
print("String转化为double后的比较的结果:$result");
//int 转化为 String
var ii = 2; int jj = 2;
print("ii和jj这两个数字相等吗?${ii==jj}");
String intToString = 2.toString();
String jjToString = jj.toString();
print("intToString和“2”这两个字符串相同吗?${intToString == "2"}");
print("jj和“2”两个字符串相同吗?${jjToString == "2"}");
double kk = 3.1415926; String doubleToString = kk.toString();
print("doubleToString和“3.1415926”相同吗?${doubleToString=="3.1415926"}");
保留小数点后指定位数的小数,这里是3,表示保留小数点后3位有效数字并且最后一位遵守四舍五入,应该就是3.145
String stringAsFixed = kk.toStringAsFixed(3);
print("stringAsFixed = ${stringAsFixed}");
保留除小数点以外的有效数字位数,这里是5,表示保留除小数点以外的5为有效数字,应该就是3.1415
String stringAsPrecision = kk.toStringAsPrecision(5);
print("stringAsPrecision = ${stringAsPrecision}");
}
运行结果如下:
int类型指定传统的按位移位(<<,>>),AND(&)和OR(|)运算符。例如:
bool rightMove = (3 << 1) == 6;
bool leftMove = (3 >> 1) == 1;
//同1为1,否则为0
int andOperation = (3 & 2);
//有1为1,否则为0
int orOperation = (3 | 2);
print("右移运算<<结果是${rightMove}, \n左移运算>>结果是${leftMove},"
"\n与运算&结果是${andOperation},\n或运算 | 结果是${orOperation}");
运行结果如下:
文字数字是编译时常量。许多算术表达式也是编译时常量,只要它们的操作数是编译为数字的编译时常量。示例:
const msPerSecond = 1000;
const secondsUntilRetry = 5;
const msUntilRetry = secondsUntilRetry * msPerSecond;
print("常量运算结果是:${msUntilRetry}");
运行结果如下:
常量运算结果是:5000
字符串代表一系列字符。例如,如果要存储一些数据,如名称,地址等,则应使用字符串数据类型。Dart字符串是一系列UTF-16代码单元。符文用于表示UTF-32代码单元序列。
关键字String用于表示字符串文字,字符串值嵌入单引号或双引号中。因此可以使用单引号或双引号来创建字符串:
void stringCharacteristic(){
var s = 'string interpolation';
print('Dart has $s, which is very handy.' ==
'Dart has string interpolation, ' +
'which is very handy.');
print('That deserves all caps. ' +
'${s.toUpperCase()} is very ' + 'handy!' ==
'That deserves all caps. ' +
'STRING INTERPOLATION is very handy!');
print('That deserves all caps. ' +
'${s.toLowerCase()} is very handy!' ==
'That deserves all caps. ' +
'string interpolation is very handy!');
}
上面3个print 打印日志,结果都是true;
开发中,我们还可以使用带有单引号(‘’)或双引号(””)的三引号创建多行字符串:
var s1 = '''
You can create
multi-line strings like this one.
''';
var s2 = """This is also a
multi-line string.""";
可以通过在前面加上 r 来创建“原始”字符串,而不发生转义:
//注意下面字符串最前面的r,因为他的存在,后面的换行符”\n”便失去了应有的意义和作用
var str01 = r'In a raw string, not even \n gets special treatment.';
var str02 = 'In a raw string, not even \n gets special treatment.';
print(str01);
print(str02);
运行结果如下:
关于const关键字修饰的常量,使用时要注意:
// 在 const 字符串中。
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
const validConstString = '$aConstNum $aConstBool $aConstString';
print("全为const常量组成一个新的常量:$validConstString");
// 不在 const 字符串中。
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];
//一般性变量和const常量没法组合成一个新的const常量,编译时就会报错爆红,如下代码:
const invalidConstString = '$aNum $aBool $aString $aConstList';
//虽然不能是const常量,但是是可以声明为final类型的常量,如下:
final invalidConstStringFinal = '$aNum $aBool $aString $aConstList';
print("一般性变量和const常量只能组合成final型常量,结果是:$invalidConstStringFinal");
Dart中的bool类型。只有两个对象具有bool类型:boolean 文字:true和false,它们都是编译时常量。
注意:在Dart语言中,所有类型的变量的默认值都是null,也就是在声明变量类型时仅仅是声明,但不赋值的情况下,默认值统统都是null,包括var关键之声明的变量默认值也是null。如下:
void boolData(){
bool booleanVar;
print("bool型变量的默认值是:$booleanVar");
String stringDefault;
var varDefault;
print("String型变量的默认值是:$stringDefault,\nvar关键字声明的变量默认值是:$varDefault");
int intDefault;
print("int型变量的默认值是:$intDefault");
}
var varName;
var varDefaultName = "";
var varValue = "运动";
print("varName是空值么?${varName == null},\nvarDefaultName是空值吗?${varDefaultName.isEmpty},\nvarValue是空值吗?${varValue.isEmpty}");
var zeroData = 0;
print("zeroData等于0吗?${zeroData == 0}");
var mod = 0/0;
print("除数为0的情况:${mod.isNaN}");
几乎每种编程语言中最常见的集合是数组或有序的对象组,其特点是元素有序且可以重复。在Dart中,数组是List对象,因此大多数人将它称为列表:
var listData = [1, 2, 3, 4, 5]; //这根Java里面的数组一样;
跟Java的数组一样,列表使用从0开始的索引,其中0是第一个元素的索引,list.length-1是最后一个元素的索引,可以直接通过下标的方式改变对应index位置的值。也可以直接通过list.length来获取列表的长度:
print("列表的第一个元素是:${listData[0]}, 第三个元素是${listData[2]}");
//跟Java的数组一样,可以直接通过下标的方式改变对应index位置的值。
listData[2] = 100;
print("列表的长度是:${listData.length}");
print("变更后列表listData的第三个元素值是:${listData[2]}");
运行结果如下:
我们还可以通过像Java的list集合那样通过add()方法在列表的末尾添加新的元素,但是Dart语言没有提供在指定的位置添加新的元素。也就是说Dart语言中的列表的长度即便是在声明并赋值之后依然是可以变更的。另外我们还可以通过remove()系列方法来删除指定条件的元素:
通过add()方法在列表的末尾添加新的元素
listData.add(9);
listData.add(33);
在指定的位置添加新的元素的方法是insert()系列方法
listData.insert(1, 23);
包含的元素有:1, 2, 100, 4, 5, 9, 33
print("新增元素后,新的列表的长度是:${listData.length}");
移除元素值为2的元素,移除之后列表包含的元素是:1, 100, 4, 5, 9, 33
listData.remove(2);
移除index = 2位置上的元素,移除之后列表包含的元素是:1, 4, 5, 9, 33
listData.removeAt(1);
移除列表最后一个元素,移除之后列表包含的元素是:1, 4, 5, 9
listData.removeLast();
print("经过一系列的操作之后,新的列表的长度是:${listData.length}");
print("列表的第一个元素是:${listData[0]}, 第二个元素是:${listData[1]}, 第三个元素是:${listData[2]},, 第4个元素是:${listData[3]}");
运行结果如下:
我们还可以创建一个const常量型的列表,但是const常量型列表的特点是:一经声明并赋值之后,就不能再变更,包括更改某个index位置的值,删除某个元素,新增元素,一旦进行上述操作就会报错抛异常:
//我们现在再来创建一个const常量数组
const constList = [1,2,3,8,10];
constList[10] = 9;
运行结果如下:
Dart 2.3引入了扩展运算符(…)和空值感知扩展运算符(…?),它提供了一种将多个元素插入集合的简洁方法。例如,使用扩展运算符(…)将列表的所有元素插入另一个列表:
const constList = [1,2,3,8,10];
var insertList = [14,...constList];
print("新的insertList长度是多少?${insertList.length}");
print("insertList第1个元素是:${insertList[0]}, 第2个元素是:${insertList[1]}, 第3个元素是:${insertList[2]}, 第4个元素是:${insertList[3]}, 第5个元素是${insertList[4]}, 第6个元素是${insertList[5]}");
如果扩展运算符右侧的表达式可能为null,则可以通过使用支持null的扩展运算符(...?)来避免异常:
var oldList;
经过这步操作后,insertList将会清空原来的数据,然后生产一个新的列表:一个只有一个元素的列表
insertList = [12, ...?oldList];
print("再次拼接后的insertList长度是多少?${insertList.length}");
Dart 2.3还引入了if和collection的集合,使用它在条件(if)和重复(for)构建集合。下面是一个使用集合的示例,如果要创建一个包含三个或四个项目的列表:
var promoActive = true;
var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet' ];
print("nav列表长度是多少?${nav.length}");
这是一个使用集合来操作列表项目,然后将它们添加到另一个列表之前的示例:
这是一个使用集合来操作列表项目,然后将它们添加到另一个列表之前的示例
var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
print("listOfStrings列表长度是多少?${listOfStrings.length}");
print("列表的第一个元素是:${listOfStrings[0]}, 第二个元素是:${listOfStrings[1]}, ""第三个元素是:${listOfStrings[2]}, 第4个元素是:${listOfStrings[3]}");
print(listOfStrings[1] == '#1');
上述代码运行结果如下:
常用API归集:
——length —— 获取数组的长度
——reversed —— 反转数组,但是返回值不是一个数组,而是一个抽象类的实例化对象,所以需要通过 toList() 转换为数组。
——isEmpty —— 检测数组是否为空,返回布尔值
——add(E e) —— 向数组的末尾添加元素,该方法没有返回值。参数只能是一个元素,也就是说,一次只能添加一个元素。
——addAll(Iterable i) —— 将一个可迭代对象中的元素添加到数组的末尾,该方法没有返回值。
——indexOf(element,start=0) —— 查找一个元素,返回这个数组在数组中的索引,如果数组中没有这个元素,则返回-1.该方法接收两个参数,第一个就是查找的元素,第二个是非必须参数,表示查找的起始位置。
——remove(element) —— 删除数组中的元素,返回一个布尔值表示删除是否成功。
——removeAt(index) —— 删除指定位置的元素,结果返回被删除的元素。
——fillRange(start,end,element) —— 填充 [start,end) 中的元素,该方法没有返回值
——insert(index,element) —— 在指定的位置插入元素,该方法没有返回值。
——insertAll(index,iterable) —— 在指定的位置插入多个元素,该方法没有返回值。
——toList() —— 将一个可迭代类型转换为数组。
——join(separator) —— 将数组转换为字符串,参数为分隔符。
——forEach(function) —— 遍历数组,该方法没有返回值:list.forEach((item) => print(item));
需要注意的是:回调函数中的参数只有一个,就是元素的值,没有索引!!而且,箭头函数只有一个参数的情况下也不能把括号省略。
1、map(function) —— 加工方法,该方法不会改变原数组,而是返回一个新的可迭代对象,参数是一个回调函数。
2、any(function) —— 遍历数组,每个元素都执行一次回调函数,判断是否满足回调函数返回值这个条件,如果有一个或以上元素满足,则返回 true。 例如:
var list = [1,2,3,4,5];
bool result = list.any((item) => item > 2);
print(result);
list的三种遍历输出方式:
var list = [1,2,3,4,5];
list.forEach((element) {
print("forEach遍历输出方式:${element}");
});
for(var i=0;i
Dart中的Set是元素无序不重复的唯一项的集合。Dart支持由Set文字和Set类型提供的集合。下是一个简单的Dart集,使用set文字创建:
var halogens = {
'yiibai.com', 'chlorine',
'bromine', 'iodine', 'astatine'
};
要创建一个空集合,请使用前面带有类型参数的{},或者将{}赋给类型为Set的变量:
要创建一个空集合,请使用前面带有类型参数的{},或者将{}赋给类型为Set的变量:
var names = {};
Set nameSet = {};
print("两个set集合相等么?${names == nameSet}");
下面这点要特别的注意(这个写法创建的将会是一个map,不是一个set集合)。
var names = {};
使用add()或addAll()方法将项添加到现有集合:
使用add()或addAll()方法将项添加到现有集合:
names.add('fluorine');
nameSet.add("value");
names.addAll(halogens);
names.addAll(nameSet);
使用set.length来获取集合中的项目数量:
使用.length来获取集合中的项目数量:
print("names集合的长度:${names.length}");
要创建一个编译时常量的集合,请在set文字之前添加const:
要创建一个编译时常量的集合,请在set文字之前添加const:
final constantSet = const { 'iodine', 'astatine', };
下面这步运行会报错:Unsupported operation: Cannot change unmodifiable set
constantSet.add('helium');
运行结果如下:
set的常用API:
——length —— 集合长度
——first —— 返回集合第一个元素
——last —— 返回集合最后一个元素
——isEmpty —— 判断集合是否空
——add(E) —— 向集合的末尾添加元素
——addAll(E) —— 把一个可迭代对象中的所有元素添加到集合的末尾
——remove(E) —— 删除某个元素
——clear() —— 清空集合
——contains(E) —— 判断集合是否包含某个元素
——containsAll(E) —— 判断集合是否包含一个可迭代对象中的所有元素
——toList() —— 转换为数组
映射是关联键key和值value的对象。键key和值value可以是任何类型的对象。每个键key只出现一次不能重复,否则后一次key键对应的值value会覆盖前一次键key存入的值value;但值value完全不受这个限制。Dart支持由映射文字和Map类型提供的映射。 这个规则跟Java里面的Map规则完全一样。
映射Map的创建方式有两种:
//这种方式适用于有限的数量且知道确切的key值的时候使用方便
var textMap = {"service": "Java", "Android": "Kotlin", "Flutter": "Dart"};
var intMap = {1:"Java",2:"C",3:"Python",4:"C++",5:"C#"};
var intConstructionMap = Map();
intConstructionMap[1] = "Java";
intConstructionMap[2] = "C";
intConstructionMap[3] = "Python";
intConstructionMap[4] = "C++";
intConstructionMap[5] = "C#";
//当我们需要新增元素的时候,调用下面的方法新增元素或者替换原本存在的元素:
textMap["System"] = "C";
intMap[6] = "VB";
strConstructionMap["System"] = "C";
intConstructionMap["auxiliary"] = "VB";
//获取元素的方式:
var getTextMapValue = textMap["System"];
var getIntMapValue = intMap[6];
var getStrConstructionMapValue = strConstructionMap["System"];
var getIntConstructionMapValue = intConstructionMap["System"];
print('getTextMapValue == ${getTextMapValue}, getIntMapValue == ${getIntMapValue}, getStrConstructionMapValue == ${getStrConstructionMapValue}, getIntConstructionMapValue == ${getIntConstructionMapValue}');
print("getIntConstructionMapValue是一个null字符串?${getIntConstructionMapValue=="null"},\ngetIntConstructionMapValue是一个null对象?${getIntConstructionMapValue==null}");
不知道大家有没有发现这个运行结果很奇怪,那就是最后的getIntConstructionMapValue的值打印出来是一个null,也就是我们并没有获取到值,并且从后面的判断结果来看,我们也可以知道系统返回给我买的是一个null对象,而不是一个“null的字符串”。但是我们明明向intConstructionMap集合添加了键key为“System”的值value“System”的啊。为什么没有获取到呢?
其实我们仔细看代码不难发现,我们前面给intConstructionMap集合添加元素的时候,用到的key值都是整数型的,但是我们在最后添加值value为“System”的时候,用到的key值确实字符串型的“System”,因为数据类型的不同,这就肯定导致了我们添加的结果是失败的。
如果我们把向intConstructionMap集合添加value为“System”的值的时候用的键key由“System”改为任意整数的话,就可以成功了:
intConstructionMap[6] = "VB";
var getIntConstructionMapValue = intConstructionMap[6];
运行结果如下:
这也表明当映射Map通过键key去查找value值的时候,如果没有查找到,就会给我们返回一个null对象。这一点在开发中要注意。
现在我们再来看看映射Map的遍历输出,映射Map还是用上面的intConstructionMap:
intConstructionMap.forEach((key, value) {
print("intConstructionMap映射的key===${key},value===${value}");
});
运行结果如下:
映射Map的常用API:
——length —— 长度
——keys —— 返回一个包含所有键的可迭代集合
——values —— 返回一个包含所有值的可迭代集合
——isEmpty —— 判断集合是否为空
——addAll() —— 添加所有迭代对象中的键值对
——remove(key) —— 删除一个键值对
print("intConstructionMap映射的长度length===${intConstructionMap.length}");
print("intConstructionMap是空的吗?${intConstructionMap.isNotEmpty}");
print("intConstructionMap包含指定的key值么?${intConstructionMap.containsKey(7)}");
print("intConstructionMap包含指定的value值么?${intConstructionMap.containsValue("VB")}");
print("textMap包含指定的key值么?${textMap.containsKey("System")}");
textMap.remove("System");
print("textMap实现remove移除指定key值的操作之后,还包含指定的key值么?${textMap.containsKey("System")}");
//下面代码的主要作用是返回包含键key和值value的迭代器集合Iterable
Iterable iterableKey = intConstructionMap.keys;
iterableKey.forEach((element) {
print("循环遍历所有值Key的可迭代集合iterableKey:key==${element}");
});
Iterable iterableValue = intConstructionMap.values;
iterableValue.forEach((element) {
print("循环遍历所有值Value的可迭代集合iterableValue:value==${element}");
});