運算子
Dart 支援下表所示的運算子。下表顯示 Dart 運算子的結合性和運算子優先順序,從最高到最低排列,這近似於 Dart 運算子的關係。您可以將許多這些運算子實作為類別成員。
描述 | 運算子 | 結合性 |
---|---|---|
一元後綴 | expr ++ expr -- () [] ?[] . ?. ! | 無 |
一元前綴 | - expr ! expr ~ expr ++ expr -- expr await expr | 無 |
乘法 | * / % ~/ | 向左 |
加法 | + - | 向左 |
位移 | << >> >>> | 向左 |
位元 AND | & | 向左 |
位元 XOR | ^ | 向左 |
位元 OR | | | 向左 |
關係和類型測試 | >= > <= < as is is! | 無 |
相等 | == != | 無 |
邏輯 AND | && | 向左 |
邏輯 OR | || | 向左 |
if-null | ?? | 向左 |
條件 | expr1 ? expr2 : expr3 | 向右 |
串聯 | .. ?.. | 向左 |
賦值 | = *= /= += -= &= ^= 等等 | 向右 |
擴展 (請參閱附註) | ... ...? | 無 |
當您使用運算子時,您會建立運算式。以下是一些運算子運算式的範例
a++
a + b
a = b
a == b
c ? a : b
a is T
運算子優先順序範例
#在運算子表格中,每個運算子的優先順序都高於後續列中的運算子。例如,乘法運算子 %
的優先順序高於 (因此執行順序先於) 相等運算子 ==
,而相等運算子 ==
的優先順序又高於邏輯 AND 運算子 &&
。這種優先順序表示以下兩行程式碼的執行方式相同
// Parentheses improve readability.
if ((n % i == 0) && (d % i == 0)) {
// ...
}
// Harder to read, but equivalent.
if (n % i == 0 && d % i == 0) {
// ...
}
算術運算子
#Dart 支援常用的算術運算子,如下表所示。
運算子 | 意義 |
---|---|
+ | 加法 |
- | 減法 |
- expr | 一元負號,也稱為負數 (反轉運算式的符號) |
* | 乘法 |
/ | 除法 |
~/ | 除法,傳回整數結果 |
% | 取得整數除法的餘數 (模數) |
範例
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder
assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');
Dart 也支援前綴和後綴遞增和遞減運算子。
運算子 | 意義 |
---|---|
++ var | var = var + 1 (運算式值為 var + 1 ) |
var ++ | var = var + 1 (運算式值為 var ) |
-- var | var = var - 1 (運算式值為 var - 1 ) |
var -- | var = var - 1 (運算式值為 var ) |
範例
int a;
int b;
a = 0;
b = ++a; // Increment a before b gets its value.
assert(a == b); // 1 == 1
a = 0;
b = a++; // Increment a after b gets its value.
assert(a != b); // 1 != 0
a = 0;
b = --a; // Decrement a before b gets its value.
assert(a == b); // -1 == -1
a = 0;
b = a--; // Decrement a after b gets its value.
assert(a != b); // -1 != 0
相等和關係運算子
#下表列出相等和關係運算子的意義。
運算子 | 意義 |
---|---|
== | 等於;請參閱以下討論 |
!= | 不等於 |
> | 大於 |
< | 小於 |
>= | 大於或等於 |
<= | 小於或等於 |
若要測試兩個物件 x 和 y 是否代表相同的事物,請使用 ==
運算子。(在極少數情況下,您需要知道兩個物件是否完全是相同的物件,請改用 identical() 函式。) 以下說明 ==
運算子的運作方式
如果 x 或 y 為 null,則如果兩者皆為 null,則傳回 true,如果只有一個為 null,則傳回 false。
傳回在 x 上以引數 y 叫用
==
方法的結果。(沒錯,==
等運算子是在其第一個運算元上叫用的方法。如需詳細資訊,請參閱運算子。)
以下是使用每個相等和關係運算子的範例
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
類型測試運算子
#as
、is
和 is!
運算子對於在執行階段檢查類型非常方便。
運算子 | 意義 |
---|---|
as | 類型轉換 (也用於指定程式庫前綴) |
is | 如果物件具有指定的類型,則為 true |
is! | 如果物件不具有指定的類型,則為 true |
如果 obj
實作 T
指定的介面,則 obj is T
的結果為 true。例如,obj is Object?
永遠為 true。
如果您確定物件屬於 T
類型,才使用 as
運算子將物件轉換為特定類型。範例
(employee as Person).firstName = 'Bob';
如果您不確定物件是否為 T
類型,則在使用物件之前,請先使用 is T
檢查類型。
if (employee is Person) {
// Type check
employee.firstName = 'Bob';
}
賦值運算子
#如您所見,您可以使用 =
運算子賦值。若要僅在賦值變數為 null 時才賦值,請使用 ??=
運算子。
// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
b ??= value;
複合賦值運算子 (例如 +=
) 將運算與賦值結合在一起。
= | *= | %= | >>>= | ^= |
+= | /= | <<= | &= | |= |
-= | ~/= | >>= |
以下說明複合賦值運算子的運作方式
複合賦值 | 等效運算式 | |
---|---|---|
對於運算子 op | a op = b | a = a op b |
範例 | a += b | a = a + b |
以下範例使用賦值和複合賦值運算子
var a = 2; // Assign using =
a *= 3; // Assign and multiply: a = a * 3
assert(a == 6);
邏輯運算子
#您可以使用邏輯運算子反轉或組合布林運算式。
運算子 | 意義 |
---|---|
! expr | 反轉下列運算式 (將 false 變更為 true,反之亦然) |
|| | 邏輯 OR |
&& | 邏輯 AND |
以下是使用邏輯運算子的範例
if (!done && (col == 0 || col == 3)) {
// ...Do something...
}
位元運算子和位移運算子
#您可以在 Dart 中操作數字的個別位元。通常,您會將這些位元運算子和位移運算子與整數搭配使用。
運算子 | 意義 |
---|---|
& | AND |
| | OR |
^ | XOR |
~ expr | 一元位元補數 (0 變成 1;1 變成 0) |
<< | 向左位移 |
>> | 向右位移 |
>>> | 不帶正負號的向右位移 |
以下是使用位元運算子和位移運算子的範例
final value = 0x22;
final bitmask = 0x0f;
assert((value & bitmask) == 0x02); // AND
assert((value & ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR
assert((value << 4) == 0x220); // Shift left
assert((value >> 4) == 0x02); // Shift right
// Shift right example that results in different behavior on web
// because the operand value changes when masked to 32 bits:
assert((-value >> 4) == -0x03);
assert((value >>> 4) == 0x02); // Unsigned shift right
assert((-value >>> 4) > 0); // Unsigned shift right
條件運算式
#Dart 有兩個運算子可讓您簡潔地評估運算式,否則可能需要 if-else 陳述式
condition
?
expr1
:
expr2
- 如果 condition 為 true,則評估 expr1 (並傳回其值);否則,評估並傳回 expr2 的值。
expr1
??
expr2
- 如果 expr1 為非 null,則傳回其值;否則,評估並傳回 expr2 的值。
當您需要根據布林運算式賦值時,請考慮使用條件運算子 ?
和 :
。
var visibility = isPublic ? 'public' : 'private';
如果布林運算式測試 null,請考慮使用 if-null 運算子 ??
(也稱為 null 聯合運算子)。
String playerName(String? name) => name ?? 'Guest';
先前的範例至少可以用另外兩種方式撰寫,但不如這種方式簡潔
// Slightly longer version uses ?: operator.
String playerName(String? name) => name != null ? name : 'Guest';
// Very long version uses if-else statement.
String playerName(String? name) {
if (name != null) {
return name;
} else {
return 'Guest';
}
}
串聯表示法
#串聯 (..
、?..
) 可讓您對同一個物件執行一系列運算。除了存取執行個體成員之外,您也可以對同一個物件呼叫執行個體方法。這通常可以省去建立暫時變數的步驟,並讓您撰寫更流暢的程式碼。
請考慮以下程式碼
var paint =
Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
建構式 Paint()
會傳回 Paint
物件。串聯表示法之後的程式碼會對此物件進行運算,忽略可能傳回的任何值。
先前的範例等效於此程式碼
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
如果串聯運算作用的物件可能為 null,則對第一個運算使用空值短路串聯 (?..
)。從 ?..
開始可保證不會對該 null 物件嘗試任何串聯運算。
document.querySelector('#confirm') // Get an object.
?..textContent =
'Confirm' // Use its members.
..classList.add('important')
..onClick.listen((e) => window.alert('Confirmed!'))
..scrollIntoView();
先前的程式碼等效於以下程式碼
final button = document.querySelector('#confirm');
button?.textContent = 'Confirm';
button?.classList.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();
您也可以巢狀串聯。例如
final addressBook =
(AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone =
(PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
請小心在傳回實際物件的函式上建構串聯。例如,以下程式碼會失敗
var sb = StringBuffer();
sb.write('foo')
..write('bar'); // Error: method 'write' isn't defined for 'void'.
sb.write()
呼叫傳回 void,而且您無法在 void
上建構串聯。
擴展運算子
#擴展運算子會評估產生集合的運算式、解壓縮產生的值,並將其插入另一個集合中。
擴展運算子實際上不是運算子運算式。...
/...?
語法是集合常值本身的一部分。因此,您可以在集合頁面上瞭解更多關於擴展運算子的資訊。
由於它不是運算子,因此語法沒有任何「運算子優先順序」。實際上,它具有最低的「優先順序」— 任何類型的運算式都可作為擴展目標,例如
[...a + b]
其他運算子
#您已在其他範例中看過其餘的大部分運算子
運算子 | 名稱 | 意義 |
---|---|---|
() | 函式應用 | 表示函式呼叫 |
[] | 下標存取 | 表示對可覆寫的 [] 運算子的呼叫;範例:fooList[1] 將整數 1 傳遞至 fooList 以存取索引 1 處的元素 |
?[] | 條件式下標存取 | 類似於 [] ,但最左邊的運算元可以是 null;範例:fooList?[1] 將整數 1 傳遞至 fooList 以存取索引 1 處的元素,除非 fooList 為 null (在這種情況下,運算式評估為 null) |
. | 成員存取 | 參照運算式的屬性;範例:foo.bar 從運算式 foo 選取屬性 bar |
?. | 條件式成員存取 | 類似於 . ,但最左邊的運算元可以是 null;範例:foo?.bar 從運算式 foo 選取屬性 bar ,除非 foo 為 null (在這種情況下,foo?.bar 的值為 null) |
! | 非 null 斷言運算子 | 將運算式轉換為其基礎的非可 null 類型,如果轉換失敗,則擲回執行階段例外狀況;範例:foo!.bar 斷言 foo 為非 null,並選取屬性 bar ,除非 foo 為 null,在這種情況下,會擲回執行階段例外狀況 |
如需關於 .
、?.
和 ..
運算子的詳細資訊,請參閱類別。
除非另有說明,否則本網站上的文件反映 Dart 3.7.1。頁面上次更新於 2025-02-12。 檢視原始碼 或 回報問題。