Flutter入门-Dart语法1-变量、常量与数据类型

130 阅读5分钟

变量声明

变量声明可以用以下方式:

var str='hello dart';
var num=123;
// 字符串类型
String str='hello dart';
// 数字类型
int num=123;

使用 var 可以自动推断类型,也可以像 Java 一样手动写上类型String

数据类型

数字

num类型,是数字类型的父类型,有两个子类 int 和 double

// 1.整数类型int
int age = 18;
int hexAge = 0x12;
print(age);
print(hexAge);

// 2.浮点类型double
double height = 1.88;
print(height);

// num是int和double的父类型
num age = 18;

字符串

Dart字符串是UTF-16编码单元的序列。您可以使用单引号或双引号创建一个字符串:

//1.定义字符串的方式
var s1 = 'Hello World';
var s2 = "Hello Dart";
var s3 = 'Hello\'Fullter';
var s4 = "Hello'Fullter";

可以使用三个单引号或者双引号表示多行字符串:

// 2.表示多行字符串的方式
var messagel = '''
哈哈哈
呵呵呵
咪嘿嘿''';

字符串拼接

在Dart中,可以使用多种方式拼接字符串

  1. 使用+
  2. 使用字符串插值(使用${expression}
  3. 使用StringBuffer类进行高效的拼接(当需要拼接大量字符串时)
String string1 = 'Hello, ';
String string2 = 'World!';
String result = string1 + string2; // 结果为 'Hello, World!'

String name = 'Dart';
String result = 'Hello, ${name}!'; // 结果为 'Hello, Dart!'

StringBuffer buffer = new StringBuffer();
buffer.write('Hello, ');
buffer.write('World!');
String result = buffer.toString(); // 结果为 'Hello, World!'

数字和字符串互转

// 字符串和数字转化
//1.字符串转数字
var one = int.parse('111');
var two = double.parse('12.22');

print('S(one) S(one.runtimeType}'); // 111 int
print('$(two) $(two.runtimeType}'); // 12.22 double

// 2.数字转字符申
var num1 = 123;
var num2 = 123.456;
var num1Str = num1.toString();
var num2Str = num2.toString();
var num2StrD = num2.toStringAsFixed(2); // 保留两位小数
print('$(num1Str) $(num1Str.runtimeType)'); // 123 String
print('$(num2Str) $(num2Str.runtimeType)'); // 123.456 String
print('$(num2StrD) $(num2StrD.runtimeType)'); // 123.46 String

布尔

布尔类型中,Dart提供了一个 bool 的类型取值为 true 和 false

var isFlag - true;
print('$(isFlag) $(isFlag.runtimeType)');

dart中无法像javascript中进行非空判断,因为dart是强类型,不会自动进行类型判断if(exper)中exper只能为true or false 而不能是''、null、0等

集合类型

对于集合类型,Dart 则内置了最常用的三种: List / set / Map
其中,list 可以这样来定义: list的声明方式

  var arr = <String>['0', '1', '2', '3']; // 定义数组类型
  var arr1 = [0, 1, 2, 3, 4]; //自动推断
	List arr5 = <String>['0', '1', '2', '3'];// 使用类型的方式定义list
  • 使用 const 关键字创建编译时变量,不能修改、增加

      var arr2 = const [1, 2, 3, 4]; // 创建一个编译时的常量,不能修改、增加
      arr2.add(5); // Cannot add to an unmodifiable list
    
  • 创建一个固定长度的集合

    	var arr3 = List.filled(2,'');// 创建一个固定长度的集合
    	var arr4 = List.filled<int>(2,0);// 创建一个固定长度的有类型的集合
    
  • 扩展操作符对数组的操作

      var list = [1, 2, 3];
      var list2 = [0, ...list]; // 将 list 插入 list2 中
      assert(list2.length == 4);
    
  • 空感知操作符对数组的操作,如果是 null 则可以避免异常

    var list;
    var list2 = [0, ...?list];
    assert(list2.length == 1);
    
  • 获取数组长度

      var arr = <String>['0', '1', '2', '3']; 
    	arr.length
    
  • 判断是否为空

      var arr = <String>['0', '1', '2', '3']; 
      arr.isEmpty
      arr.isNotEmpty
    
  • 翻转数组

      var arr = ['1', '2'];
      var newArr = arr.reversed.toList();
      print(newArr);
    
  • 在 List 中可以使用 if 或 for

      var nav = ['Home', 'Furniture', 'Plants', if (true) 'Outlet'];
      var listOfInts = [1, 2, 3];
      var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
      print(listOfStrings); // [#0, #1, #2, #3]
    

Set 和 List 最大的两个不同就是: set 是无序的,并且元素是不重复的

// Set的定义
// 1.使用类型推导定义
  var lettersSet = {'a', 'b', 'c', 'd'};
  print('$lettersSet ${lettersSet.runtimeType}');

// 2.明确指定类型
  Set<int> numbersSet = {1, 2, 3, 4};
  print("$numbersSet ${numbersSet.runtimeType}");
  
  //增加元素
  var sets = <Object>{};
  sets.add('1');
  sets.addAll([1, 2, 3]);
  print(sets);
  
  //长度
  print(sets.length);
  
  //展开运算符
  final sets = {'fluorine', 'chlorine'};
  var maybeNull;
  final a = <String>{'hello', ...sets};
  final b = <String>{'hello', ...?maybeNull};
  print(a);
  print(b);

最后,Map 是我们常说的字典类型

  const a = [1, 2, 3];
  var map = {a: '123'}; // map 当 js 的map 用,key 不用写成[key]
  var map1 = <String,String>{'a': '123'}; // map 当js 的 object用,key需要加引号
  var map2 = Map(); // 创建自由类型的 map,可以加 new
  var map3 = Map<int, String>(); // 创建 map 时定义类型
  map3[1] = '1'; // 给 map 赋值
  print(map);
  print(map1);
  print(map.containsKey(a)); // js的 map.has 方法判断是否有这个 key
  map1['asdads'] //null; //不存在的键值对返回null
  
  //增加键值对
  var map = {};
  map['age'] = 20;
  map.addAll({"name": 'qiuyanxi', 1: 2});
  print(map);
  
  //展开运算符
  var map = {'name': "qiuyanxi"};
  Map? maybeNull;
  var newMap = {...map};
  var newMap2 = {...?maybeNull};

const和final

常量可以用 final 和 const 修饰符来声明,这两个关键字可以替代 var或者加在类型前面。

final

final name='some name';
const age=20;
const int age = 123;
final List list = [];

final包含了const的功能,区别在于:

  • final 可以一开始不赋值,如果赋值了则只赋值一次。const 一开始就需要赋值
  • const 必须给一个明确的编译常量值(即编译期间就确定的值
  • final 可以通过计算/函数获取一个值(即运行期间确定的值
  • final 不仅有 const 编译时的常量的特性,而且是惰性初始化,即在运行时第一次使用前才初始化

举个例子

  // 报错了 const一开始就需要赋值  The constant 'a' must be initialized.
	const a; 
  // 报错了 Const variables must be initialized with a constant value.
  const a = new DateTime.now();

  final b;
  b = new DateTime.now(); // 不会报错

const 变量是编译时常量。如果使用 const 修饰类中的变量,则必须加上 static 关键字,即 static const

const

在声明 const 变量时可以直接为其赋值,也可以使用其它的 const 变量为其赋值。

const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere

const 关键字不仅仅用来定义常量,还可以用来创建常量值,该常量值可以赋予给任何变量。也可以将构造函数声明为 const,这种类型的构造函数创建的对象是不可改变的。

  var foo = const [];
  final bar = const [];
  const baz = []; // 相当于`const []`

使用初始化表达式为常量赋值就可以省略掉关键字 const,比如常量 bar 的赋值就省略掉了 const。

使用 const 变量还能够创建一个类似单例的对象,比如下面的语法,能够创建一个相同的对象

class Person {
  final String name;
  const Person(this.name);
}

void main(List<String> args) {
  const p1 = const Person('myname');
  const p2 = Person('myname'); // const 可以省略
  print(identical(p1, p2));// 这两个对象是相等的
}

Objecr和dynamic

所有变量引用的都是对象,每个对象都是一个类的实例。数字、函数以及nulll都是对象。除了null外(如果开启了空安全),所有类都继承于Object类。 Object 是所有类的基类,相当于一个可以兼容所有类型的超级类型。dynamic 就是一个动态类,类似 TypeScript 的 any。

在下面代码中,如果用 Object 类声明会过不了编译。

  Object a = 'String';
  a.subString(1); //❌The method 'subString' isn't defined for the type 'Object'

换成dynamic就表示这是动态类型,可以绕过编译检查。

  dynamic a = 'String';
  a.substring(1);