dart:core
dart:core 库(API 参考)提供了一小部分但至关重要的内置功能。此库会自动导入到每个 Dart 程序中。
打印到控制台
#
顶级 print()
方法接受一个单一参数(任意 Object),并在控制台中显示该对象的字符串值(由 toString()
返回)。
print(anObject);
print('I drink $tea.');
有关基本字符串和 toString()
的更多信息,请参阅语言之旅中的“字符串”部分。
数字
#
dart:core 库定义了 num、int 和 double 类,这些类包含一些用于处理数字的基本工具。
你可以使用 int 和 double 的 parse()
方法分别将字符串转换为整数或双精度浮点数:
assert(int.parse('42') == 42);
assert(int.parse('0x42') == 66);
assert(double.parse('0.50') == 0.5);
或者使用 num 的 parse() 方法,如果可能则创建一个整数,否则创建一个 double:
assert(num.parse('42') is int);
assert(num.parse('0x42') is int);
assert(num.parse('0.50') is double);
要指定整数的基数,请添加一个 radix
参数:
assert(int.parse('42', radix: 16) == 66);
使用 toString()
方法将 int 或 double 转换为字符串。要指定小数点右侧的位数,请使用 toStringAsFixed()。要指定字符串中的有效位数,请使用 toStringAsPrecision():
// Convert an int to a string.
assert(42.toString() == '42');
// Convert a double to a string.
assert(123.456.toString() == '123.456');
// Specify the number of digits after the decimal.
assert(123.456.toStringAsFixed(2) == '123.46');
// Specify the number of significant figures.
assert(123.456.toStringAsPrecision(2) == '1.2e+2');
assert(double.parse('1.2e+2') == 120.0);
更多信息,请参阅 int、double 和 num 的 API 文档。另请参阅 dart:math 部分。
字符串和正则表达式
#
Dart 中的字符串是不可变的 UTF-16 代码单元序列。语言教程中有更多关于字符串的信息。您可以使用正则表达式(RegExp 对象)在字符串中搜索并替换字符串的某些部分。
字符串类定义了如 split()
、 contains()
、 startsWith()
、 endsWith()
等方法。
在字符串中搜索
#
您可以在字符串中查找特定位置,以及检查字符串是否以特定模式开头或结尾。例如:
// Check whether a string contains another string.
assert('Never odd or even'.contains('odd'));
// Does a string start with another string?
assert('Never odd or even'.startsWith('Never'));
// Does a string end with another string?
assert('Never odd or even'.endsWith('even'));
// Find the location of a string inside a string.
assert('Never odd or even'.indexOf('odd') == 6);
从字符串中提取数据
#
你可以将字符串中的单个字符分别作为字符串或整数获取。准确地说,你实际上获取的是单个 UTF-16 码元;像高音谱号符号('\u{1D11E}')这样的高编号字符每个由两个码元组成。
您还可以提取子字符串或将字符串拆分为子字符串列表:
// Grab a substring.
assert('Never odd or even'.substring(6, 9) == 'odd');
// Split a string using a string pattern.
var parts = 'progressive web apps'.split(' ');
assert(parts.length == 3);
assert(parts[0] == 'progressive');
// Get a UTF-16 code unit (as a string) by index.
assert('Never odd or even'[0] == 'N');
// Use split() with an empty string parameter to get
// a list of all characters (as Strings); good for
// iterating.
for (final char in 'hello'.split('')) {
print(char);
}
// Get all the UTF-16 code units in the string.
var codeUnitList = 'Never odd or even'.codeUnits.toList();
assert(codeUnitList[0] == 78);
在许多情况下,您希望处理 Unicode 字形簇,而不是纯代码单元。这些是用户感知到的字符(例如,“🇬🇧”是一个用户感知到的字符,但由多个 UTF-16 代码单元组成)。为此,Dart 团队提供了 characters
包。
转换为大写或小写
#
您可以轻松地将字符串转换为它们的大写和小写变体:
// Convert to uppercase.
assert('web apps'.toUpperCase() == 'WEB APPS');
// Convert to lowercase.
assert('WEB APPS'.toLowerCase() == 'web apps');
修剪和空字符串
#
使用 trim()
删除所有前导和尾随空格。要检查字符串是否为空(长度为零),请使用 isEmpty
。
// Trim a string.
assert(' hello '.trim() == 'hello');
// Check whether a string is empty.
assert(''.isEmpty);
// Strings with only white space are not empty.
assert(' '.isNotEmpty);
替换字符串的一部分
#
字符串是不可变对象,这意味着您可以创建它们但不能更改它们。如果您仔细查看字符串 API 参考文档,您会注意到没有任何方法实际上会改变字符串的状态。例如,方法 replaceAll()
返回一个新的字符串,而不改变原始字符串:
var greetingTemplate = 'Hello, NAME!';
var greeting = greetingTemplate.replaceAll(RegExp('NAME'), 'Bob');
// greetingTemplate didn't change.
assert(greeting != greetingTemplate);
构建字符串
#
要编程生成一个字符串,您可以使用 StringBuffer。StringBuffer 在调用 toString()
之前不会生成一个新的 String 对象。 writeAll()
方法有一个可选的第二个参数,允许您指定一个分隔符——在这种情况下,是一个空格。
var sb = StringBuffer();
sb
..write('Use a StringBuffer for ')
..writeAll(['efficient', 'string', 'creation'], ' ')
..write('.');
var fullString = sb.toString();
assert(fullString == 'Use a StringBuffer for efficient string creation.');
Regular expressions
#The RegExp class provides the same capabilities as JavaScript regular expressions. Use regular expressions for efficient searching and pattern matching of strings.
// Here's a regular expression for one or more digits.
var numbers = RegExp(r'\d+');
var allCharacters = 'llamas live fifteen to twenty years';
var someDigits = 'llamas live 15 to 20 years';
// contains() can use a regular expression.
assert(!allCharacters.contains(numbers));
assert(someDigits.contains(numbers));
// Replace every match with another string.
var exedOut = someDigits.replaceAll(numbers, 'XX');
assert(exedOut == 'llamas live XX to XX years');
You can work directly with the RegExp class, too. The Match class provides access to a regular expression match.
var numbers = RegExp(r'\d+');
var someDigits = 'llamas live 15 to 20 years';
// Check whether the reg exp has a match in a string.
assert(numbers.hasMatch(someDigits));
// Loop through all matches.
for (final match in numbers.allMatches(someDigits)) {
print(match.group(0)); // 15, then 20
}
More information
#Refer to the String API reference for a full list of methods. Also see the API reference for StringBuffer, Pattern, RegExp, and Match.
Collections
#Dart ships with a core collections API, which includes classes for lists, sets, and maps.
Lists
#As the language tour shows, you can use literals to create and initialize lists. Alternatively, use one of the List constructors. The List class also defines several methods for adding items to and removing items from lists.
// Create an empty list of strings.
var grains = <String>[];
assert(grains.isEmpty);
// Create a list using a list literal.
var fruits = ['apples', 'oranges'];
// Add to a list.
fruits.add('kiwis');
// Add multiple items to a list.
fruits.addAll(['grapes', 'bananas']);
// Get the list length.
assert(fruits.length == 5);
// Remove a single item.
var appleIndex = fruits.indexOf('apples');
fruits.removeAt(appleIndex);
assert(fruits.length == 4);
// Remove all elements from a list.
fruits.clear();
assert(fruits.isEmpty);
// You can also create a List using one of the constructors.
var vegetables = List.filled(99, 'broccoli');
assert(vegetables.every((v) => v == 'broccoli'));
Use indexOf()
to find the index of an object in a list:
var fruits = ['apples', 'oranges'];
// Access a list item by index.
assert(fruits[0] == 'apples');
// Find an item in a list.
assert(fruits.indexOf('apples') == 0);
Sort a list using the sort()
method. You can provide a sorting function that compares two objects. This sorting function must return < 0 for smaller, 0 for the same, and > 0 for bigger. The following example uses compareTo()
, which is defined by Comparable and implemented by String.
var fruits = ['bananas', 'apples', 'oranges'];
// Sort a list.
fruits.sort((a, b) => a.compareTo(b));
assert(fruits[0] == 'apples');
Lists are parameterized types (generics), so you can specify the type that a list should contain:
// This list should contain only strings.
var fruits = <String>[];
fruits.add('apples');
var fruit = fruits[0];
assert(fruit is String);
fruits.add(5); // Error: 'int' can't be assigned to 'String'
Refer to the List API reference for a full list of methods.
Sets
#A set in Dart is an unordered collection of unique items. Because a set is unordered, you can't get a set's items by index (position).
// Create an empty set of strings.
var ingredients = <String>{};
// Add new items to it.
ingredients.addAll(['gold', 'titanium', 'xenon']);
assert(ingredients.length == 3);
// Adding a duplicate item has no effect.
ingredients.add('gold');
assert(ingredients.length == 3);
// Remove an item from a set.
ingredients.remove('gold');
assert(ingredients.length == 2);
// You can also create sets using
// one of the constructors.
var atomicNumbers = Set.from([79, 22, 54]);
Use contains()
and containsAll()
to check whether one or more objects are in a set:
var ingredients = Set<String>();
ingredients.addAll(['gold', 'titanium', 'xenon']);
// Check whether an item is in the set.
assert(ingredients.contains('titanium'));
// Check whether all the items are in the set.
assert(ingredients.containsAll(['titanium', 'xenon']));
An intersection is a set whose items are in two other sets.
var ingredients = Set<String>();
ingredients.addAll(['gold', 'titanium', 'xenon']);
// Create the intersection of two sets.
var nobleGases = Set.from(['xenon', 'argon']);
var intersection = ingredients.intersection(nobleGases);
assert(intersection.length == 1);
assert(intersection.contains('xenon'));
Refer to the Set API reference for a full list of methods.
Maps
#A map, commonly known as a dictionary or hash, is an unordered collection of key-value pairs. Maps associate a key to some value for easy retrieval. Unlike in JavaScript, Dart objects are not maps.
You can declare a map using a terse literal syntax, or you can use a traditional constructor:
// Maps often use strings as keys.
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu']
};
// Maps can be built from a constructor.
var searchTerms = Map();
// Maps are parameterized types; you can specify what
// types the key and value should be.
var nobleGases = Map<int, String>();
You add, get, and set map items using the bracket syntax. Use remove()
to remove a key and its value from a map.
var nobleGases = {54: 'xenon'};
// Retrieve a value with a key.
assert(nobleGases[54] == 'xenon');
// Check whether a map contains a key.
assert(nobleGases.containsKey(54));
// Remove a key and its value.
nobleGases.remove(54);
assert(!nobleGases.containsKey(54));
You can retrieve all the values or all the keys from a map:
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu']
};
// Get all the keys as an unordered collection
// (an Iterable).
var keys = hawaiianBeaches.keys;
assert(keys.length == 3);
assert(Set.from(keys).contains('Oahu'));
// Get all the values as an unordered collection
// (an Iterable of Lists).
var values = hawaiianBeaches.values;
assert(values.length == 3);
assert(values.any((v) => v.contains('Waikiki')));
To check whether a map contains a key, use containsKey()
. Because map values can be null, you cannot rely on simply getting the value for the key and checking for null to determine the existence of a key.
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu']
};
assert(hawaiianBeaches.containsKey('Oahu'));
assert(!hawaiianBeaches.containsKey('Florida'));
Use the putIfAbsent()
method when you want to assign a value to a key if and only if the key does not already exist in a map. You must provide a function that returns the value.
var teamAssignments = <String, String>{};
teamAssignments.putIfAbsent('Catcher', () => pickToughestKid());
assert(teamAssignments['Catcher'] != null);
Refer to the Map API reference for a full list of methods.
Common collection methods
#List, Set, and Map share common functionality found in many collections. Some of this common functionality is defined by the Iterable class, which List and Set implement.
Use isEmpty
or isNotEmpty
to check whether a list, set, or map has items:
var coffees = <String>[];
var teas = ['green', 'black', 'chamomile', 'earl grey'];
assert(coffees.isEmpty);
assert(teas.isNotEmpty);
要将对每个列表、集合或映射中的项应用函数,可以使用 forEach()
:
var teas = ['green', 'black', 'chamomile', 'earl grey'];
teas.forEach((tea) => print('I drink $tea'));
当您在映射上调用 forEach()
时,您的函数必须接受两个参数(键和值):
hawaiianBeaches.forEach((k, v) {
print('I want to visit $k and swim at $v');
// I want to visit Oahu and swim at
// [Waikiki, Kailua, Waimanalo], etc.
});
可迭代对象提供了 map()
方法,该方法将所有结果返回在一个单一对象中:
var teas = ['green', 'black', 'chamomile', 'earl grey'];
var loudTeas = teas.map((tea) => tea.toUpperCase());
loudTeas.forEach(print);
要强制您的函数在每个项目上立即被调用,请使用 map().toList()
或 map().toSet()
:
var loudTeas = teas.map((tea) => tea.toUpperCase()).toList();
使用 Iterable 的 where()
方法获取所有符合某个条件的项。使用 Iterable 的 any()
和 every()
方法检查某些或所有项是否符合某个条件。
var teas = ['green', 'black', 'chamomile', 'earl grey'];
// Chamomile is not caffeinated.
bool isDecaffeinated(String teaName) => teaName == 'chamomile';
// Use where() to find only the items that return true
// from the provided function.
var decaffeinatedTeas = teas.where((tea) => isDecaffeinated(tea));
// or teas.where(isDecaffeinated)
// Use any() to check whether at least one item in the
// collection satisfies a condition.
assert(teas.any(isDecaffeinated));
// Use every() to check whether all the items in a
// collection satisfy a condition.
assert(!teas.every(isDecaffeinated));
要获取完整的方法列表,请参考 Iterable API 参考文档,以及 List、Set 和 Map 的相关文档。
统一资源标识符
#
Uri 类提供了用于在 URI(你可能知道它是 URL)中编码和解码字符串的函数。这些函数处理对 URI 特殊的字符,例如 &
和 =
。Uri 类还解析并公开 URI 的各个组成部分——主机、端口、方案等等。
编码和解码完全合格的 URI
#
要对 URI 中具有特殊意义的字符(例如 /
、 :
、 &
、 #
)进行编码和解码,请使用 encodeFull()
和 decodeFull()
方法。这些方法适用于对完整合格的 URI 进行编码或解码,同时保留特殊的 URI 字符。
var uri = 'https://example.org/api?foo=some message';
var encoded = Uri.encodeFull(uri);
assert(encoded == 'https://example.org/api?foo=some%20message');
var decoded = Uri.decodeFull(encoded);
assert(uri == decoded);
请注意,只有 some
和 message
之间的空格被编码了。
编码和解码 URI 组件
#
要对字符串中在 URI 中有特殊意义的所有字符进行编码和解码,包括(但不限于) /
、 &
和 :
,请使用 encodeComponent()
和 decodeComponent()
方法。
var uri = 'https://example.org/api?foo=some message';
var encoded = Uri.encodeComponent(uri);
assert(
encoded == 'https%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message');
var decoded = Uri.decodeComponent(encoded);
assert(uri == decoded);
请注意每个特殊字符是如何编码的。例如, /
被编码为 %2F
。
解析 URI
#
如果您有一个 Uri 对象或 URI 字符串,您可以使用 Uri 字段(例如 path
)来获取其各个部分。要从字符串创建一个 Uri,请使用 parse()
静态方法:
var uri = Uri.parse('https://example.org:8080/foo/bar#frag');
assert(uri.scheme == 'https');
assert(uri.host == 'example.org');
assert(uri.path == '/foo/bar');
assert(uri.fragment == 'frag');
assert(uri.origin == 'https://example.org:8080');
请参阅 Uri API 参考文档,了解更多您可以获取的 URI 组件。
构建 URI
#
您可以使用 Uri()
构造函数从各个部分构建 URI:
var uri = Uri(
scheme: 'https',
host: 'example.org',
path: '/foo/bar',
fragment: 'frag',
queryParameters: {'lang': 'dart'});
assert(uri.toString() == 'https://example.org/foo/bar?lang=dart#frag');
If you don't need to specify a fragment, to create a URI with a http or https scheme, you can instead use the Uri.http
or Uri.https
factory constructors:
var httpUri = Uri.http('example.org', '/foo/bar', {'lang': 'dart'});
var httpsUri = Uri.https('example.org', '/foo/bar', {'lang': 'dart'});
assert(httpUri.toString() == 'http://example.org/foo/bar?lang=dart');
assert(httpsUri.toString() == 'https://example.org/foo/bar?lang=dart');
Dates and times
#A DateTime object is a point in time. The time zone is either UTC or the local time zone.
You can create DateTime objects using several constructors and methods:
// Get the current date and time.
var now = DateTime.now();
// Create a new DateTime with the local time zone.
var y2k = DateTime(2000); // January 1, 2000
// Specify the month and day.
y2k = DateTime(2000, 1, 2); // January 2, 2000
// Specify the date as a UTC time.
y2k = DateTime.utc(2000); // 1/1/2000, UTC
// Specify a date and time in ms since the Unix epoch.
y2k = DateTime.fromMillisecondsSinceEpoch(946684800000, isUtc: true);
// Parse an ISO 8601 date in the UTC time zone.
y2k = DateTime.parse('2000-01-01T00:00:00Z');
// Create a new DateTime from an existing one, adjusting just some properties:
var sameTimeLastYear = now.copyWith(year: now.year - 1);
The millisecondsSinceEpoch
property of a date returns the number of milliseconds since the "Unix epoch"—January 1, 1970, UTC:
// 1/1/2000, UTC
var y2k = DateTime.utc(2000);
assert(y2k.millisecondsSinceEpoch == 946684800000);
// 1/1/1970, UTC
var unixEpoch = DateTime.utc(1970);
assert(unixEpoch.millisecondsSinceEpoch == 0);
Use the Duration class to calculate the difference between two dates and to shift a date forward or backward:
var y2k = DateTime.utc(2000);
// Add one year.
var y2001 = y2k.add(const Duration(days: 366));
assert(y2001.year == 2001);
// Subtract 30 days.
var december2000 = y2001.subtract(const Duration(days: 30));
assert(december2000.year == 2000);
assert(december2000.month == 12);
// Calculate the difference between two dates.
// Returns a Duration object.
var duration = y2001.difference(y2k);
assert(duration.inDays == 366); // y2k was a leap year.
For a full list of methods, refer to the API reference for DateTime and Duration.
Utility classes
#The core library contains various utility classes, useful for sorting, mapping values, and iterating.
Comparing objects
#Implement the Comparable interface to indicate that an object can be compared to another object, usually for sorting. The compareTo()
method returns < 0 for smaller, 0 for the same, and > 0 for bigger.
class Line implements Comparable<Line> {
final int length;
const Line(this.length);
@override
int compareTo(Line other) => length - other.length;
}
void main() {
var short = const Line(1);
var long = const Line(100);
assert(short.compareTo(long) < 0);
}
Implementing map keys
#Each object in Dart automatically provides an integer hash code, and thus can be used as a key in a map. However, you can override the hashCode
getter to generate a custom hash code. If you do, you might also want to override the ==
operator. Objects that are equal (via ==
) must have identical hash codes. A hash code doesn't have to be unique, but it should be well distributed.
class Person {
final String firstName, lastName;
Person(this.firstName, this.lastName);
// Override hashCode using the static hashing methods
// provided by the `Object` class.
@override
int get hashCode => Object.hash(firstName, lastName);
// You should generally implement operator `==` if you
// override `hashCode`.
@override
bool operator ==(Object other) {
return other is Person &&
other.firstName == firstName &&
other.lastName == lastName;
}
}
void main() {
var p1 = Person('Bob', 'Smith');
var p2 = Person('Bob', 'Smith');
var p3 = 'not a person';
assert(p1.hashCode == p2.hashCode);
assert(p1 == p2);
assert(p1 != p3);
}
Iteration
#The Iterable and Iterator classes support sequential access to a collection of values. To practice using these collections, follow the Iterable collections tutorial.
If you create a class that can provide Iterators for use in for-in loops, extend (if possible) or implement Iterable. Implement Iterator to define the actual iteration ability.
class Process {
// Represents a process...
}
class ProcessIterator implements Iterator<Process> {
@override
Process get current => ...
@override
bool moveNext() => ...
}
// A mythical class that lets you iterate through all
// processes. Extends a subclass of [Iterable].
class Processes extends IterableBase<Process> {
@override
final Iterator<Process> iterator = ProcessIterator();
}
void main() {
// Iterable objects can be used with for-in.
for (final process in Processes()) {
// Do something with the process.
}
}
Exceptions
#The Dart core library defines many common exceptions and errors. Exceptions are considered conditions that you can plan ahead for and catch. Errors are conditions that you don't expect or plan for.
A couple of the most common errors are:
- NoSuchMethodError
- Thrown when a receiving object (which might be
null
) does not implement a method. - ArgumentError
- Can be thrown by a method that encounters an unexpected argument.
Throwing an application-specific exception is a common way to indicate that an error has occurred. You can define a custom exception by implementing the Exception interface:
class FooException implements Exception {
final String? msg;
const FooException([this.msg]);
@override
String toString() => msg ?? 'FooException';
}
For more information, see Exceptions (in the language tour) and the Exception API reference.
Weak references and finalizers
#Dart is a garbage-collected language, which means that any Dart object that isn't referenced can be disposed by the garbage collector. This default behavior might not be desirable in some scenarios involving native resources or if the target object can't be modified.
A WeakReference stores a reference to the target object that does not affect how it is collected by the garbage collector. Another option is to use an Expando to add properties to an object.
A Finalizer can be used to execute a callback function after an object is no longer referenced. However, it is not guaranteed to execute this callback.
A NativeFinalizer provides stronger guarantees for interacting with native code using dart:ffi; its callback is invoked at least once after the object is no longer referenced. Also, it can be used to close native resources such as a database connection or open files.
To ensure that an object won't be garbage collected and finalized too early, classes can implement the Finalizable interface. When a local variable is Finalizable, it won't be garbage collected until the code block where it is declared has exited.
Unless stated otherwise, the documentation on this site reflects Dart 3.5.3. Page last updated on 2024-06-10. View source or report an issue.