dart 替代java_Dart对比java快速入门

[TOC]

定位

首先本文是通过对比其他语言(主要是java)快速入门,建议您至少要熟悉一门静态语言或者动态语言。Dart和java以及C#都差不多,基本上不用学习可以直接使用,从这里可以你可以了解Dart有些特别之处。

首先从一段代码入门吧:

void main() {

for (int i = 0; i < 5; i++) {

printTest('hello ${i + 1}');

}

}

void printTest(String variableInteger) {

print(variableInteger);

}

从上面可以看到,Dart语言主入口是main函数,他可以不用属于某个类。一眼看上去和java差不多。流程控制也是由小括号和大括号构成,不用考虑缩进。结尾必须要加上分号。

声明数据类型

void main() {

int l = 4;

String str1 = "str1";

var i = 1;

dynamic d = 0;

final j = 2;

const k = 3;

}

Dart是强类型语言,变量都会有一个类型。你可以向java那样直接声明类型,同样可以像swift或者Kotlin那样使用类型推导。Dart的类型推导使用final,var,const,dynamic关键字。

var修饰变量,这个没什么好说的。

final表示不可变的,修饰内置数据类型,值不可变;修饰对象表示引用不可变,使用到的频率很高。

const是编译时常量,他表示始终不可变,无论修饰内置类型还是对象,或者是数据结构。

dynamic是任意类型,有点像java里面的Object,Kotlin中的Any。

使用const修饰的都是编译时常量。它区别于运行时,它的值是不可变的。

所有的数据类型,不管是int还是String,初始值都是null

数据类型

numbers、strings和booleans

首先是numbers,strings,booleans其中numbers包括int和double类型,分别表示整数和浮点数。strings就是String类型,普通的字符串。booleans类型是bool只包含true和false。

numbers

* int

* double

strings

* String

booleans

* bool

如下代码:

void main() {

// numbers

int i = 1;

double d = 1.1;

// 字符串转数字

// 这里就使用了类型推导

final p1 = "3";

final p2 = "3.3";

print(int.parse(p1));

print(double.parse(p2));

// string

// 可以使用('xxx')("xxx")('''xxx''') 三种方式初始化字符串,和Kotlin很像。

// 字符串比较的是值

final str1 = "test";

final str2 = "test";

print(str1 == str2); // true

final str3 = 'test';

print(str3);

final str4 = '''test''';

print(str4);

print(str4 == str3); // true

print("I'm ${str4}!!!");

//booleans

// null 可以直接用来判断,它是false

if(null) {

print('null is true');

} else {

print('null is false');

}

print(''.isEmpty);

// final list = [];

// if(!list) {

// print('not empty');

// }

}

Dart的数据结构包括list和map

list

list对应的就是java里面的List,list可以像Python等语言那样使用[]进行数组操作,参照以下示例代码。

List有几个在flutter非常常用的初始化方式,分别为filled和generate。具体参考:https://api.dartlang.org/stable/2.1.0/dart-core/List-class.html

void main() {

// 初始化

final list1 = [1,2,3,4,5];

// 编译时常量

final list2 = const [2,3,4,5,6];

// list2[2] = 8; error

print(list2);

// 初始化2

List list3 = new List(5);

print(list3); // [null, null, null, null, null]

// 初始化3 filled 第一个参数是个数,第二个是添加的值

List list4 = List.filled(3,10);

print(list4); // [10,10,10]

// 初始化4 类似Python的Map生成

List list5 = List.generate(3,(i) => i * 3);

print(list5); // [0, 3, 6]

// 更改 使用list1

list1[2] = 8;

print(list1); // [1, 2, 8, 4, 5]

// 添加

list1.add(10);

// list1[10] = 20; Index out of range

print(list1); // [1, 2, 8, 4, 5, 10]

//删除

list1.remove(10);

print(list1); // [1, 2, 8, 4, 5]

}

map

map 对应java里面的Map,他的操作方式有点像Python。需要注意的有几点。

Map的Key不能有重复的

如果使用int类型作为key,取值的时候优先使用key匹配,然后是下标。

取不到值不会抛异常,直接返回null

Map和List可以转换为Json,来回转换时深拷贝。

import 'dart:convert';

void main() {

final map1 = {

"test1key" : "test1value",

// "test1key" : "test1value", Key 不能相同

123 : "123value",

null : 'NULL',

2 : '2'

};

print(map1); // {test1key: test1value, 123: 123value, null: NULL, 2: 2}

// 获取值

print(map1[123]); // key取值 123value

print(map1[1]); // 下标取值 null

print(map1[2]); // 同时存在时候,优先Key取值;结果为 2

// 追加值

map1['appendKey'] = 'appendVal';

print(map1);

// 更改值

map1['appendKey'] = 'appendVal123';

print(map1);

map1['appendKey'] = null;

print(map1); // 置为null之后,key不会消失

map1.remove('appendKey');

// 删除

print(map1);

print(map1['non-key']); // 不会报错 打印 null

print(map1.length); // 长度 4

// json 转换

// 使用const修饰的数据结构,不可改变。

final map2 = const {

"name":"lecon",

"age":23,

"ss":[1,2,3,4,4]

};

final jsonText = jsonEncode(map2);

print(jsonText); // {"name":"lecon","age":23,"ss":[1,2,3,4,4]}

final mapObj = jsonDecode(jsonText);

print(mapObj); // {name: lecon, age: 23, ss: [1, 2, 3, 4, 4]}

}

Runes

这东西其实就是字符集的扩编,可以用它显示一些表情符号

main() {

var clapping = '\u{1f44f}';

print(clapping);

print(clapping.codeUnits);

print(clapping.runes.toList());

Runes input = new Runes(

'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');

print(new String.fromCharCodes(input));

}

函数

Dart的函数比java多了几个概念。比如在参数列表里面添加个大括号,是可选命名参数;加个中括号叫可选位置参数。

可选命名参数类似Python里面的**kwargs,参考下面示例代码func3;

可选位置参数类似Python里面的*args,参考下面func5。

可选命名参数和可选位置参数可以有默认值,普通参数不能有,参考func6。

函数之间可以互相嵌套,互相调用,但他们都有自己作用域。

若果函数简单可以使用()=> value简写。

比如

String test() {

return "123";

}

简写成

String test ()=> "123";

下面是示例代码

// import 'package:meta/meta.dart'

void main() {

func1(123);

func2('222');

func3("lecon");

// func3("lecon","spawn",123); error,使用下边的中括号,注意区别。这个使用key区分,下面使用位置区分

func3("lecon",param2:"spawn",param3:123);

// func4("lecon",param2:"spawn"); error required

func5("lecon","spawn","hahaa");

func6("lecon",age:25);

print(func7());

}

void func1(param1) {

print(param1);

}

void func2(String param2) {

print(param2);

}

void func3(String param1,{String param2,int param3}) {

print("I am ${param1}, Hi ${param2},I am ${param3}");

}

// test in flutter

// void func4(String param1,{String param2,@required int param3}) {

// print("I am ${param1}, Hi ${param2},I am ${param3}");

// }

void func5(String param1,[String param2,String param3]) {

print("I am ${param1}, bian bu ${param2} xia qu le ${param3}");

}

// 只有使用{}和[]的才可以有默认值

void func6(String param1,{int age = 23}) {

print("I am ${param1}, I am ${age}");

}

func7() {

void func8() {

}

void func9() {

}

retrun () => "123";

}

流程控制

Dart的流程控制和java的用法基本一样,这里就不介绍了。

有个for in要说下,和JavaScript很像。

for (var x in collection) {}

相当于java的高级for循环

for(Integer i : indexs) {}

面向对象

相对于java有这几点需要注意

new关键字可以省略

一个类同名构造器只能有一个,也就是说可以给构造器起其他名字。所以可以把构造器分为默认构造器和命名构造器。

命名构造器不能自动继承,参考下面

Dart使用this代表当前对象

初始化列表

Dart有继承和接口概念,和java基本差不多,同时多了个混入的的概念minix,这个非常好理解。

下面这个例子是类构造器的基本使用

普通构造器和继承

class Person {

String name;

int age;

String dantengt;

// 注意,冒号后边是初始化列表,用,隔开。

Person() :dantengt = "danm";

@override

String toString() => "name : ${name};age : ${age}";

}

class Person2 {

String name;

int age;

// 默认构造器只能声明一个

// 不用写set方法,使用this可以直接把值赋给相应的属性

Person2(this.name,this.age);

// 命名构造器

Person2.copy(Person p) {

this.name = p.name;

this.age = p.age;

}

@override

String toString() => "name : ${name};age : ${age}";

}

class Student extends Person2 {

final String school;

// 普通构造器继承

Student(String name,int age,this.school):super(name,age);

// 命名构造器的继承

Student.copy(Person p,this.school):super.copy(p);

// 类似构造器的重载

Student.mySchoolCopy(Person p):this.copy(p,'mySchool');

}

// 所有值都不可以改变

class ImmutablePoint {

static final ImmutablePoint origin =

const ImmutablePoint(0, 0);

final num x, y;

// cosnt修饰的构造器是常量构造器,里面的值都不许改变。因为是编译时的。

const ImmutablePoint(this.x, this.y);

}

void main() {

final person = Person();

person.name = "spawn";

person.age = 18;

print(person);

final person2 = Person2("lecon",25);

print(person2);

print(Person2.copy(person));

Person2 p2 = Student("lecon",25,"haha");

// is 和 as ;类似 instanceof和强转

if (p2 is Student) {

(p2 as Student).school;

}

}

其中:

Person类的构造器后面有个:,那个就是初始化列表,可以给属性赋值(参考Person类),还可调用父类构造器。

Person2 类有两个构造器,默认构造器没有名字,和java中一样使用类名声明。另外还有一个Person2.copy() 他也是一个构造器,只不过它有名字了,同名构造器只能出现一次,不管是不是重载(貌似Dart没重载)。

在构造器参数列表中,如果直接使用this关键字,可以直接把值付给类的属性,省去了set方法(参考类Person2的默认构造器)。

在类中,所有的属性或者方法,只要带了_前缀,那么他就是私有的,Dart文件之外不能访问,当前文件不同类是可以的。

is关键字相当于instanceof ,as相当于强转。这个和Kotlin很像。

const修饰构造器,代表类是编译时的。所有内容不允许改变。

类的继承使用extends关键字,同时dart也有接口,和java基本一致,不再赘述。

除了继承和接口之外,Dart还有个mixin混入的概念,可以把他理解为:把其他类的东西,一股脑放到当前类中,使用with关键字描述。

minix

关于minix参考以下代码:

// class关键字换成minix,其他和class一样,只是换个名字。

mixin Play {

void play() {

print("I can play");

}

}

mixin Eat {

void eat() {

print("I can eat");

}

}

// 使用with关键字加入mixin类

class Person with Play,Eat {

final String name;

final int age;

Person(this.name,this.age);

}

void main() {

final p = Person("lecon",13);

// 此时p有了Eat和Play的能力

p.play();

p.eat();

}

factory构造器和多态

java编程中,在使用多态的时候,我们可能会用到工厂方法,dart给我们提供一个方便,使用dart的工厂构造器。dart的工厂构造器也是个构造器,只不过使用factory修饰,他返回当前类,并且不能使用this关键字,示例代码。

class Person2 {

String name;

int age;

Person2(this.name,this.age);

// factory 构造器也是构造器,同样不能声明两个相同名字的,而且只能有一个默认

// factory 没有this引用

factory Person2.select(name,int age,int type) {

if(type == 0) {

return Student(name,age,"jaja");

} else {

return Worker(name,age,"lala");

}

}

// callable

call(String a, String b, String c) => '$a $b $c!';

@override

String toString() => "name : ${name};age : ${age}";

}

class Student extends Person2 {

final String school;

Student(String name,int age,this.school):super(name,age);

}

class Worker extends Person2 {

final String company;

Worker(String name,int age,this.company):super(name,age);

}

void main() {

// 不关注Person2实现类,直接使用Person2实例化。使用factory

final p1 = Person2.select("lecon",23,0);

final p2 = Person2.select("lecon",23,1);

print(p1.runtimeType); // Student

print(p2.runtimeType); // Worker

// callable

print(p1("123","234","345"));

}

其中select为Person2的工厂构造器,由它来返回对应的实现类。

setter和getter

很多语言里面,为了方便获取属性都提供了setter和getter。其实他就是个语法糖。直接使用就可以。看例子:

class Rectangle {

num left, top, width, height;

Rectangle(this.left, this.top, this.width, this.height);

num get right => left + width;

set right(num value) => left = value - width;

num get bottom => top + height;

set bottom(num value) => top = value - height;

}

void main() {

var rect = Rectangle(3, 4, 20, 15);

assert(rect.left == 3);

rect.right = 12;

assert(rect.left == -8);

}

异常

Dart的异常也和java非常像。直接看例子

void main() {

// throw1();

// throw2();

// throw3();

// throw4();

throw5();

}

void throw1() {

throw FormatException('Expected at least 1 section');

}

void throw2() {

throw 'Expected at least 1 section';

}

void throw3() {

try {

throw FormatException('Expected at least 1 section');

} on FormatException {

print('section exception');

}

try {

throw FormatException('Expected at least 1 section');

} on FormatException catch(e) {

print('section exception ${e}');

}

try {

throw FormatException('Expected at least 1 section');

} on FormatException catch(e,s) {

print('section exception ${e}');

print(s); // 打印方法调用栈

}

}

void throw4() {

try {

throw FormatException('Expected at least 1 section');

} on FormatException {

print('section exception');

rethrow; // 重抛

}

}

void throw5() {

try {

throw FormatException('Expected at least 1 section');

} on FormatException {

print('section exception');

} finally {

print("I am finally");

}

}

dart可以直接抛出默认异常,throw 'Expected at least 1 section';

使用on来匹配异常类型,on FormatException

使用catch来获取异常变量,catch(e,s)它有一个默认参数和可选参数。分别为信息和调用栈。

使用rethrow重新抛出异常

异步

dart的异步和JavaScript ES6差不多,使用await和async,只不过ES6中的Promise变成了Future。目前比较流行的解决方案都是这个,比如Python,Kotlin都这么使用。一般在网络请求或者数据库操作时候使用,就像java的多线程基础版吧。

生成器

Dart的生成成器和其他语言里面的生成器差不多,分为同步和异步两种。同步生成器结构是Iterable,异步生成器接口是Stream。流程控住使用async*(异步)和sync*(同步)声明,使用yield流程控制,每一次yield都会给列表生成一个值,也就是说生成器返回结果的数据结构可以当列表使用。以下代码:

void main() {

print(naturalsTo(10)); // (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

print(naturalsDownFrom(10)); // (10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

asynchronousNaturalsTo(10)

.toList() // toList把异步转为同步

.then((res) {

print(res); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

});

}

// 同步生成器

Iterable naturalsTo(int n) sync* {

int k = 0;

while (k < n) yield k++;

}

// 异步生成器

Stream asynchronousNaturalsTo(int n) async* {

int k = 0;

while (k < n) yield k++;

}

// 递归性质的生成器

Iterable naturalsDownFrom(int n) sync* {

if (n > 0) {

yield n;

yield* naturalsDownFrom(n - 1);

}

}

其他

import关键字

import 'package:lib1/lib1.dart';

import 'package:lib2/lib2.dart' as lib2;

// 仅导入foo

import 'package:lib1/lib1.dart' show foo;

// 排除foo

import 'package:lib2/lib2.dart' hide foo;

// 异步导入

import 'package:greetings/hello.dart' deferred as hello;

空判断

Dart也有null类型,并且和其他语言类似,Dart也是用?来解决空问题。

void main() {

final a = null;

print(a != null ? a : "b"); // 等同于下边,dart也支持三元运算符

print(a ?? "b"); // 打印 b

String p = null;

print(p?.toString()); //打印null,而不会空指针

}

..运算符

Dart的联级运算符..很有意思,很实用的语法糖,直接看代码你就明白了。Builder大法好。

void main() {

// 联级运算符

final p = Person()

..username = "lecon"

..password = "123456"

..setSex(true);

print(p); // Username: lecon; Password: 123456; Sex: true

}

class Person {

String _username;

String _password;

bool _sex;

set username(String username) => this._username = username;

set password(String password) => this._password = password;

void setSex(bool sex) => this._sex = sex;

@override

String toString() => "Username: ${this._username}; Password: ${this._password}; Sex: ${this._sex}";

}

Typedefs

注释

Dart注释分为三种,单行注释和多行注释和java一致。doc注释使用 ///表示。

/// A domesticated South American camelid (Lama glama).

///

/// Andean cultures have used llamas as meat and pack

/// animals since pre-Hispanic times.

最后

临时总结,难免有错误,请多多指出,我会在第一时间改正。

代码地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值