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() 方法,如果可能,它會建立整數,否則會建立雙精度浮點數
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 物件) 在字串中搜尋和取代字串的部分內容。
String 類別定義了 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);
取代字串的一部分
#字串是不可變的物件,這表示您可以建立它們,但無法變更它們。如果您仔細查看 String API 參考,,您會注意到沒有任何方法實際上會變更 String 的狀態。例如,方法 replaceAll()
會傳回新的 String,而不會變更原始 String
var greetingTemplate = 'Hello, NAME!';
var greeting = greetingTemplate.replaceAll(RegExp('NAME'), 'Bob');
// greetingTemplate didn't change.
assert(greeting != greetingTemplate);
建構字串
#若要以程式設計方式產生字串,您可以使用 StringBuffer。在呼叫 toString()
之前,StringBuffer 不會產生新的 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.');
正規表示式
#RegExp 類別提供與 JavaScript 正規表示式相同的功能。使用正規表示式可有效率地搜尋和比對字串的模式。
// Here's a regular expression for one or more digits.
var digitSequence = RegExp(r'\d+');
var lettersOnly = 'llamas live fifteen to twenty years';
var someDigits = 'llamas live 15 to 20 years';
// contains() can use a regular expression.
assert(!lettersOnly.contains(digitSequence));
assert(someDigits.contains(digitSequence));
// Replace every match with another string.
var exedOut = someDigits.replaceAll(digitSequence, 'XX');
assert(exedOut == 'llamas live XX to XX years');
您也可以直接使用 RegExp 類別。Match 類別提供對正規表示式比對的存取權。
var digitSequence = RegExp(r'\d+');
var someDigits = 'llamas live 15 to 20 years';
// Check whether the reg exp has a match in a string.
assert(digitSequence.hasMatch(someDigits));
// Loop through all matches.
for (final match in digitSequence.allMatches(someDigits)) {
print(match.group(0)); // 15, then 20
}
更多資訊
#如需完整的方法列表,請參閱 String API 參考。另請參閱 StringBuffer、 Pattern、 RegExp、 和 Match 的 API 參考。
集合
#Dart 隨附核心集合 API,其中包括用於列表、集合和映射的類別。
Lists (列表)
#如語言導覽所示,您可以使用常值來建立和初始化 列表。或者,使用 List 建構子之一。List 類別也定義了幾個用於新增項目到列表和從列表中移除項目的方法。
// 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'));
使用 indexOf()
尋找物件在列表中的索引
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()
方法排序列表。您可以提供比較兩個物件的排序函數。此排序函數對於較小的物件必須傳回 < 0,對於相同的物件傳回 0,對於較大的物件傳回 > 0。以下範例使用 compareTo()
,它由 Comparable 定義,並由 String 實作。
var fruits = ['bananas', 'apples', 'oranges'];
// Sort a list.
fruits.sort((a, b) => a.compareTo(b));
assert(fruits[0] == 'apples');
列表是參數化類型 (泛型),因此您可以指定列表應包含的類型
// 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'
如需完整的方法列表,請參閱 List API 參考。
Sets (集合)
#Dart 中的集合是唯一項目的無序集合。由於集合是無序的,因此您無法依索引 (位置) 取得集合的項目。
// 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]);
使用 contains()
和 containsAll()
檢查一個或多個物件是否在集合中
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']));
交集是一個集合,其項目位於另兩個集合中。
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'));
如需完整的方法列表,請參閱 Set API 參考。
Maps (映射)
#映射 (通常稱為字典或 hash) 是鍵值對的無序集合。映射將鍵與某些值相關聯,以便輕鬆檢索。與 JavaScript 不同,Dart 物件不是映射。
您可以使用簡潔的常值語法宣告映射,也可以使用傳統的建構子
// 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>();
您可以使用括號語法新增、取得和設定映射項目。使用 remove()
從映射中移除鍵及其值。
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));
您可以從映射中檢索所有值或所有鍵
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')));
若要檢查映射是否包含鍵,請使用 containsKey()
。由於映射值可以是 null,因此您不能僅依賴於取得鍵的值並檢查 null 來判斷鍵是否存在。
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu'],
};
assert(hawaiianBeaches.containsKey('Oahu'));
assert(!hawaiianBeaches.containsKey('Florida'));
當您想要在鍵不存在於映射中時才將值指派給鍵時,請使用 putIfAbsent()
方法。您必須提供傳回值的函數。
var teamAssignments = <String, String>{};
teamAssignments.putIfAbsent('Catcher', () => pickToughestKid());
assert(teamAssignments['Catcher'] != null);
如需完整的方法列表,請參閱 Map API 參考。
常見的集合方法
#List、Set 和 Map 共用許多集合中常見的功能。其中一些常見功能由 Iterable 類別定義,List 和 Set 實作了該類別。
使用 isEmpty
或 isNotEmpty
檢查列表、集合或映射是否具有項目
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.
});
Iterables 提供 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 的 API 參考。
URIs
#Uri 類別提供用於編碼和解碼字串以便在 URI 中使用的函數 (您可能將其稱為 URLs)。這些函數處理 URI 的特殊字元,例如 &
和 =
。Uri 類別也會剖析並公開 URI 的組件—主機、埠、scheme 等等。
編碼和解碼完整 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
。
剖析 URIs
#如果您有 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 組件,請參閱 Uri API 參考。
建構 URIs
#您可以使用 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');
如果您不需要指定片段,若要建立具有 http 或 https scheme 的 URI,您可以改用 Uri.http
或 Uri.https
工廠建構子
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');
日期和時間
#DateTime 物件是時間中的一個點。時區可以是 UTC 或本機時區。
您可以使用多個建構子和方法建立 DateTime 物件
// 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);
日期的 millisecondsSinceEpoch
屬性會傳回自「Unix epoch」(1970 年 1 月 1 日,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);
使用 Duration 類別計算兩個日期之間的差異,並將日期向前或向後移動
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.
如需完整的方法列表,請參閱 DateTime 和 Duration 的 API 參考。
公用程式類別
#核心程式庫包含各種公用程式類別,適用於排序、映射值和迭代。
比較物件
#實作 Comparable 介面以指示物件可以與另一個物件比較,通常用於排序。compareTo()
方法對於較小的物件傳回 < 0,對於相同的物件傳回 0,對於較大的物件傳回 > 0。
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);
}
實作映射鍵
#Dart 中的每個物件都會自動提供整數雜湊碼,因此可以用作映射中的鍵。但是,您可以覆寫 hashCode
getter 以產生自訂雜湊碼。如果您這樣做,您可能也想要覆寫 ==
運算子。透過 ==
相等的物件必須具有相同的雜湊碼。雜湊碼不必是唯一的,但應該分佈良好。
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);
}
迭代
#Iterable 和 Iterator 類別支援循序存取值集合。若要練習使用這些集合,請遵循可迭代集合教學課程。
如果您建立一個類別,可以為 for-in 迴圈提供 Iterators,請擴充 (如果可能) 或實作 Iterable。實作 Iterator 以定義實際的迭代能力。
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.
}
}
例外
#Dart 核心程式庫定義了許多常見的例外和錯誤。例外被認為是您可以提前計劃和捕獲的條件。錯誤是您不期望或不計劃的條件。
一些最常見的錯誤是
- NoSuchMethodError
- 當接收物件 (可能是
null
) 未實作方法時擲回。 - ArgumentError
- 可能會由遇到非預期引數的方法擲回。
擲回應用程式特定的例外是指出發生錯誤的常見方式。您可以透過實作 Exception 介面來定義自訂例外
class FooException implements Exception {
final String? msg;
const FooException([this.msg]);
@override
String toString() => msg ?? 'FooException';
}
如需更多資訊,請參閱例外 (在語言導覽中) 和 Exception API 參考。
弱參考和 Finalizers
#Dart 是一種 垃圾回收 語言,這表示任何未被參照的 Dart 物件都可以由垃圾回收器處置。在某些涉及原生資源或目標物件無法修改的情況下,此預設行為可能不是理想的。
WeakReference 儲存對目標物件的參考,這不會影響垃圾回收器收集它的方式。另一個選項是使用 Expando 將屬性新增至物件。
Finalizer 可用於在物件不再被參照後執行回呼函數。但是,不保證會執行此回呼。
NativeFinalizer 為使用 dart:ffi 與原生程式碼互動提供更強的保證;其回呼會在物件不再被參照後至少呼叫一次。此外,它可用於關閉原生資源,例如資料庫連線或開啟的檔案。
若要確保物件不會過早被垃圾回收和最終化,類別可以實作 Finalizable 介面。當本機變數為 Finalizable 時,它在宣告它的程式碼區塊結束之前不會被垃圾回收。
除非另有說明,否則本網站上的文件反映的是 Dart 3.7.1。頁面上次更新於 2025-02-21。 檢視原始碼 或 回報問題。