变量
void main() {
//var在声明变量(编译时)的那一刻决定了什么类型
var a = 1212;
// a = "sss";//报错,编译确定类型后无法再更改
//dynamic和对象Object在运行中确定类型(Object比dynamic性能要好)
dynamic b = "1212";
b = 1212;
Object c = "1212";
c = 1212;
//final是运行时确定常量,const是编译器确定常量(编译确定效率更高)
final int d = 22;
final e = 10;//可以省略类型
const int f = 11;
const g = 22;//可以省略类型
// const h = d;//报错,编译时常量无法赋值为运行时常量
final i = f;//反之不报错
//变量类型后面加问号,忽略空安全检查,可以直接使用值为空的变量而不会编译报错
String? h;
print(h);
}
内置类型
//dart七大类型(和java不同,全是引用类型)
void main() {
/**
* 1.数值类型,父类都是num;
*/
//int编码的时候占用字节大小动态确定,可以当做java的short和long使用
int a = 9223372036854775807;
//dart中没有float,不区分单双精度
double aa = 1.11;
/**
* 2.字符串类型
*/
String b = "aaa";
//字符串拼接
//方式一(无法拼接非字符串类型):
String c = b + "aaa";
//方式二:
String d = "$b加数值$a";
print(d);
//使用单引号在外面,里层双引号无需使用转义符
String e = '"aaa"';
print(e);
//r前缀表示原始字符串
// String f = "\n";//打印换行
String f = r"\n";//打印\n
print(f);
//三引号,可以换行书写(打印结果也换行)
String g = """aaaaaaaaaaa
bbbbbbbbbbbbbb
ccccccccccccccccc""";
print(g);
/**
* 3.布尔类型bool
*/
bool h = true;
/**
* 4.数组List
*/
List<int> list = [1, 2, 3, 4];
//取值
int item0 = list[0];
//iter模板遍历
for (int item in list) {//in相当于java的冒号
//sout模板打印
print(item);
}
//itar模板遍历
for (int i = 0; i < list.length; i++) {
print(list[i]);
}
//常量数组
const List<int> list1 = [1, 2, 3];
// list1 = [2, 3];//编译报错,因为该数组不能重新改变引用对象
// list1.add(111);//运行报错
List<int> list2 = const [1, 2, 3];
list2 = [2, 3];//正常
// list2.add(2);//运行报错,因为const修饰的引用的对象不能变
final List<int> list3 = [1, 2, 3];
// list3 = [2, 3];//编译报错,因为该数组不能重新改变引用对象
list3.add(111);//正常
/**
* 5.映射集合Map
*/
Map<String, String> map1 = new Map();
//添加或者修改
map1["1"] = "a";
map1["2"] = "b";
map1["3"] = "c";
map1["1"] = "d";
//直接创建有默认值的Map
Map<int, String> map2 = {1:"a", 2:"b", 3:"c"};
//遍历
//迭代器遍历
var keys = map1.keys;
for (var key in keys) {
print(map1[key]);
}
//Map对象直接遍历
map2.forEach((key, value) {
print("$key$value");
});
/**
* 6.Runes:java中没有,特殊字符(Unicode32)表示类
* 不常用,涉及到代码点和代码单元的知识点
*/
/**
* 7.Symbols:标识符
* 不常用,相当于C的宏
*/
var flag = #AAA;
print(flag.runtimeType);//打印对象类型
switch(flag) {
case #AAA :
break;
case #BBB :
break;
}
}
操作符
//操作符
void main() {
num a = 1;
//类型转换,和java强转不一样
int b = a as int;
print(b.runtimeType);
//a是否是int类型
if (a is int) {
print("true");
}
//a是否不是int类型
if (a is! int) {
print("false");
}
String c = "111";
String? d;
//赋值表达式 ??= 表示 如果前者为null,则把后者的值赋给前者
d ??= c;
print(d);
d = null;
//条件表达式 ?? 表示 如果前者不为null,则返回前者,否则返回后者
String? e = d ?? "222";
print(e);
//条件三元表达式 a = bool ? c : d; 和java一样
e = null;
//级联操作符 ..调用方法能在后面继续用..调用该类的其他方法,相当于构造者模式
new Build()..A()..B();
//安全操作符 ?. 可以让为空的变量调用方法且不报空指针
print(e?.length);
Build? bNull;
bNull?..A()..B();
}
class Build {
void A() {
print("A");
}
void B() {
print("B");
}
}
操作符重载
void main() {
Point p1 = new Point();
p1.x = 1;
Point p2 = new Point();
p2.x = 4;
Point p3 = p1 + p2;
print(p3.x);
}
class Point {
int? x;
int? y;
//操作符重载
Point operator +(Point other) {
Point p = new Point();
p.x = x! + other.x!;
return p;
}
}
异常
void main() {
//通过on加类型过滤抛出的异常类型
try {
test();
} on Exception catch (e, s) {
print(e.runtimeType);
print(e);//异常类型和说明
print(s.runtimeType);
print(s);//异常发生位置,调用栈信息
} on String catch (e, s) {
print(e.runtimeType);
print(e);//异常类型和说明
print(s.runtimeType);
print(s);//异常发生位置,调用栈信息
} on int catch (e, s) {
print(e.runtimeType);
print(e);//异常类型和说明
print(s.runtimeType);
print(s);//异常发生位置,调用栈信息
} on Function catch (e, s) {
print(e.runtimeType);
print(e);//异常类型和说明
print(s.runtimeType);
print(s);//异常发生位置,调用栈信息
//调用抛出的方法
e();
}
}
//异常万物皆可抛
void test() {
print("test");
// throw new Exception("2121");//抛常规异常
// throw "2222";//抛String
// throw 2222;//抛int
throw fun;//抛方法
}
void fun() {
print("fun");
}
方法
//使用typedef将一个方法封装为F类型,方便下面调用
typedef int F(int i, int j);
void main() {
//Function方法对象
Function f = fun;
//匿名方法来实现F方法
f((int i, int j) {
return i + j;
});
Function f1 = fun1;
//按照顺序参数赋值进行调用
f1(3);
f1(5, 1);
Function f2 = fun2;
//指定参数名赋值进行调用
f2(j:11);
f2(i:2, j:2);
}
//方法中传方法替代了java中接口的功能
void fun(F f) {
int a = f(1, 2);
print(a);
}
//可选位置参数 中括号
void fun1([int i = 1, int j = 2]) {
print(i + j);
}
//可选命名参数 大括号
void fun2({int i = 1, int j = 2}) {
print(i + j);
}
构造方法
//作用域
//默认表示公开作用域
//下划线命名开头表示私有作用域
class Point {
int? x;
int? _y;
//支持可选命名构造方法,一般不用
// Point({int? x, int? y}) {
// this.x = x;
// this._y = y;
// }
//使用以下构造方法简洁,可读性强
Point(this.x, this._y);
//dart方法不能够重载,使用命名构造方法解决
Point.no();
Point.x(this.x);
Point.y(this._y);
//参数初始化列表构造,冒号后面给参数赋值
Point.formMap(Map<String, int> map) : x=map["x"], _y=map["y"];
//重定向构造方法
Point.other(int x) : this(x, 0);
//常量构造方法
//工厂构造方法
}
void main() {
var point = new Point(2, 2);
point.x = 1;
var pointMap = new Point.formMap({"x":22, "y":44});
print(pointMap.x);
}
get和set
void main() {
Point point = new Point();
//隐式set
point.x = 10;
//隐式get
int? y = point.y;
//调用自定的get和set
point.setZ = 11;
int? zz = point.getZ;
}
class Point {
int? x;
int? y;
int? _z;
//私有参数的get和set
int? get getZ => _z;
set setZ(int value) => _z = value;
}
抽象类与接口
abstract class Father {
//抽象方法不需要abstract
void fa();
}
class Child extends Father {
@override
void fa() {
print("fa");
}
}
//所有非abstract都可视为接口实现
class IntF {
void a(){
print("IntF");
}
}
class A implements IntF {
@override
void a() {
print("A");
}
call(){
print("call");
}
}
void main() {
A a = new A();
a.a();
//调用类中的call方法,相当于a.call(),此语法必须类中有call方法
a();
}
混合
class A {
void a() {
print("a");
}
}
class B {
void b() {
print("b");
}
void a() {
print("ba");
}
}
//A,B类不能有构造函数
//若A和B中有相同方法,则调用B的(从后往前,但自身优先级最高,会覆盖AB的方法)
class C with A,B {
// 调用A中的a方法
// void a() {
// A a = new A();
// a.a();
// }
void c() {
print("c");
}
//会覆盖B类方法,但不影响B类使用
void b() {
print("cb");
}
}
//D类没有自己的成员和方法可以简写
class D = Object with A,B;
void main() {
//满足了多继承需求
C c = new C();
c.a();
c.b();
c.c();
}