默认值
如果变量未被初始化,变量的值为null
int lineCount;
assert(lineCount == null);
注:assert()的调用在生产阶段会被忽略
赋值
用??=给空对象赋值
// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
b ??= value;
final & const
final变量只能设值一次且需要在第一次使用时设值,const变量为编译期常量(隐式final)
注:实例变量可以为final,但不能为const。final的实例变量必须在构造器之前初始化,如变量声明、构造参数,或者构造器的初始化列表
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
const变量的值为数字、字符串,或他们的计算结果
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
const值
var foo = const [];
final bar = const [];
const baz = []; // Equivalent to `const []`
你可以修改非final,非const的变量,即使他的值为const
foo = [1, 2, 3]; // Was const []
内建数据类型
numbers
只包含int和double类型,且int不大于64bits,double为64bit
int会自动转为double
double z = 1; // Equivalent to double z = 1.0.
strings
Dart的string是一串UTF-16编码的字符,可以用单引号或双引号来创建
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";
如果变量为表达式,可通过${expression}在创建字符串时来引用,如果是变量可以省略{},对象的话会默认调用toString()方法
var s = 'string interpolation';
assert('Dart has $s, which is very handy.' ==
'Dart has string interpolation, ' +
'which is very handy.');
assert('That deserves all caps. ' +
'${s.toUpperCase()} is very handy!' ==
'That deserves all caps. ' +
'STRING INTERPOLATION is very handy!');
字符串可以通过相邻或者+来拼接
var s1 = 'String '
'concatenation'
" works even over line breaks.";
assert(s1 ==
'String concatenation works even over '
'line breaks.');
var s2 = 'The + operator ' + 'works, as well.';
assert(s2 == 'The + operator works, as well.');
如果要创建的是多行的字符串(包含换行),用三个引号包裹即可
var s1 = '''
You can create
multi-line strings like this one.
''';
var s2 = """This is also a
multi-line string.""";
如果要创建原始的非转义字符串,需要用r开头(和python相同)
var s = r'In a raw string, not even \n gets special treatment.';
booleans(true/false)
Dart为类型安全,所以不能像javascript那样使用if (nonbooleanValue) 或 assert (nonbooleanValue)
lists
List代表有序集合,在Dart中的数组即为List对象
//Dart推断list代表List,如果添加非int型对象会发出异常警告
var list = [1, 2, 3];
sets
Set代表无序集合
//Dart推断set代表Set,只能添加string对象
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
创建一个空的set,需要指明类型,如
var names = {};
// Set names = {}; // This works, too.
// var names = {}; // Creates a map of Map, not a set.
注:小心创建了一个map对象
要创建一个编译期的常量,需要添加const前导
final constantSet =
const {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
// constantSet.add('helium'); // Uncommenting this causes an error.
maps
两种初始化方式
//方式1
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
//方式2
var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
构建编译期的常量时,需要添加前导const
final constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
// constantMap[2] = 'Helium'; // Uncommenting this causes an error.
runes
代表UTF-32编码的字符串
fromCharCodes
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));
}
console output
[55357, 56399]
[128079]
♥
当进行字符处理时,需要当心包含runes的情况,如
void main() {
//一种情况
var input = "Music \u{1f44d} for the win"; // Music for the win
print(input.split('').reversed.join()); // niw eht rof �� cisuM
print(new String.fromCharCodes(input.runes.toList().reversed)); // niw eht rof cisuM
//另一种情况
var input2 = 'Ame\u{301}lie'; // Amélie
print(new String.fromCharCodes(input2.runes.toList().reversed)); // eiĺemA
}
symbols
Symbol对象代表声明的运算符或者标识符,你可能永远都不需要Symbol
通过#跟随标识符获取symbol
#radix
#bar
函数对象(Functions)
箭头表达式
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
注:=> expr;语法是{ return expr; }的简写,在=>和;之间只能是表达式,不能是其他如if
可选参数
Optional positional parameters
必选参数在前,可选参数在后
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
Optional named parameters
通过{param1, param2, ...}的格式命名参数,用@required标记为必选参数,通过参数名称传值( 即paramName: value)方式调用
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, @required bool hidden}) {...}
//使用时
enableFlags(bold: true, hidden: false);
参数默认值
定义时通过=赋值,且默认值必须是编译期常量,未赋值默认为null
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {...}
// bold will be true; hidden will be false.
enableFlags(bold: true);
main函数
任何app都必须包括一个顶级的main(),作为app的入口函数,main()必须返回void,并有一个可选的List
void main() {
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
}
..语法是作为级联调用的
匿名函数
格式
([[Type] param1[, …]]) {
codeBlock;
};
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
如果函数体只有一条语句,可以用箭头语法替换
list.forEach(
(item) => print('${list.indexOf(item)}: $item'));
Lexical scope(词法范围)
Dart是一种词汇范围的语言,这意味着变量的范围是静态确定的,只需通过代码的布局。您可以“沿大括号向外”查看变量是否在范围内。
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
Lexical closures(词法闭包)
closure(闭包)可以访问他所在的lexical scope(词法范围)的变量,即使被用到了在他原有的范围之外
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
// Create a function that adds 4.
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
特殊运算符
condition ? expr1 : expr2
如果condition为true,则调用expr1,否则调用expr2
expr1 ?? expr2
如果expr1非空,返回expr1的值,否则返回expr2的值
Cascade notation (..)
用前一个对象作为级联对象
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = '[email protected]'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
?.
和.运算符类似,如foo?.bar,如果foo非空,返回foo.bar,否则返回null
控制语句
switch and case
switch语句可以比较integer,string,或者用==比较编译期常量。待比较的对象必须是同一个类(不能为子类),并且这个类不能复写了==。枚举类适合switch语句。
注:某些情况下break不可缺少
var command = 'OPEN';
switch (command) {
case 'OPEN':
executeOpen();
// ERROR: Missing break
case 'CLOSED':
executeClosed();
break;
}
支持空的case,此时允许穿透
var command = 'CLOSED';
switch (command) {
case 'CLOSED': // Empty case falls through.
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
如果真的需要穿透,需要借助continue语句
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
executeClosed();
continue nowClosed;
// Continues executing at the nowClosed label.
nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
try/throw/rethrow/catch/finally
- Dart可以throw任何对象,不仅限于exception
- 在判断throw时,on或者catch都可以(也可以同时使用),用on表示只关心抛出的类型,用catch表示关心抛出的具体对象
- catch时,堆栈为可选参数,即第一个参数为抛出的对象,第二个为堆栈(StackTrace)堆栈
- 通过rethrow,重新抛出该异常
捕获单个throw
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
捕获多个throw
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
带堆栈,并继续抛出异常
try {
// ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
rethrow;// Allow callers to see the exception.
}