Dart Operators
Operators are symbols that perform calculations, comparisons, and logical judgments in programs.
This chapter systematically introduces various operators in Dart, including arithmetic, relational, logical, assignment, conditional operators, and type checking.
Arithmetic Operators
Arithmetic operators are used to perform basic mathematical operations.
Example
int a = 10;
int b = 3;
print('a = $a, b = $b');
print('Addition a + b = ${a + b}'); // 13
print('Subtraction a - b = ${a - b}'); // 7
print('Multiplication a * b = ${a * b}'); // 30
print('Division a / b = ${a / b}'); // 3.333... (result is double)
print('Integer division a ~/ b = ${a ~/ b}'); // 3 (integer part, discarding decimal)
print('Modulo a % b = ${a % b}'); // 1 (modulo operation)
print('Negation -a = ${-a}'); // -10 (unary minus)
}
a = 10, b = 3 加法 a + b = 13 减法 a - b = 7 乘法 a * b = 30 除法 a / b = 3.3333333333333335 整除 a ~/ b = 3 取余 a % b = 1 取反 -a = -10
Note: The / operator always returns a double type, even when both operands are int and evenly divisible. If you only need an integer result, use the ~/ integer division operator.
Increment and Decrement Operators
Like most C-family languages, Dart supports ++ (increment) and -- (decrement).
Example
int count = 0;
// Prefix ++: increment first, then use
print('Prefix ++: ${++count}'); // 1
// Postfix ++: use first, then increment
print('Postfix ++: ${count++}'); // 1 (count is still 1 at this point)
print('Now count = $count'); // 2
// Same for decrement
print('Prefix --: ${--count}'); // 1
print('Postfix --: ${count--}'); // 1
print('Now count = $count'); // 0
}
前置 ++: 1 后置 ++: 1 现在 count = 2 前置 --: 1 后置 --: 1 现在 count = 0
Prefix and postfix increment/decrement have the same effect when used alone, but behave differently within expressions. Beginners are advised to avoid using them in expressions as much as possible; writing them on a separate line is clearer.
Relational Operators
Relational operators are used to compare two values, and the result is a bool value.
| Operators | Meaning | Example | Result |
|---|---|---|---|
| == | equals | 5 == 5 | true |
| != | Not equal | 5 != 3 | true |
| > | greater than | 5 > 3 | true |
| < | less than | 5 < 3 | false |
| >= | greater than or equal to | 5 >= 5 | true |
| <= | less than or equal to | 3 <= 5 | true |
Example
int exampleScore = 95;
int passLine = 60;
print(Score: $exampleScore, Pass line: $passLine);
print(Passed? ${exampleScore >= passLine});
print(Full score? ${exampleScore == 100});
// Strings can also be compared
String a = 'apple';
String b = 'banana';
print("'$a' == '$b'? ${a == b}");
// == checks whether values are equal
String c = 'EXAMPLE';
String d = 'EXAMPLE';
print("'$c' == '$d'? ${c == d}"); // true (same content)
}
分数: 95, 及格线: 60 及格了吗? true 满分了吗? false 'apple' == 'banana'? false 'EXAMPLE' == 'EXAMPLE'? true
In Dart, == compares whether the values of two objects are equal, not their reference addresses. This differs from Java—in Dart, you don't need to use the equals() method to compare strings.
Logical Operators
Logical operators are used to combine multiple bool expressions, usually for conditional judgments.
| Operators | Meaning | Description |
|---|---|---|
| && | Logical AND | Returns true only if both sides are true. |
| || | Logical OR | Returns true if either side is true. |
| ! | Logical NOT | Negation: true becomes false, false becomes true |
Example
bool isLoggedIn = true;
bool isAdmin = false;
// && AND: both are true
print(Logged in and is admin: ${isLoggedIn && isAdmin}); // false
// || OR: at least one is true
print(Logged in or is admin: ${isLoggedIn || isAdmin}); // true
// ! NOT: negation
print(Not logged in: ${!isLoggedIn}); // false
// Short-circuit evaluation: if the left side already determines the result, the right side will not execute
int age = 20;
// age > 18 is already true, but the right side also needs to be checked
print(Adult and has permission: ${age >= 18 && isAdmin});
// age < 18 is already false, so the right side of && is skipped directly
print('Underage and has permission: ${age < 18 && isAdmin}');
}
登录且是管理员: false 登录或是管理员: true 未登录: false 成年且有权限: false 未成年且有权限: false
Dart usesShort-circuit EvaluationFor &&, if the left side is false, the right side is not evaluated; for ||, if the left side is true, the right side is not evaluated.
This feature can be used to avoid null pointer issues.
Example
Practical applications of short-circuit evaluation:
String? username;
// Safety check: username is not null and length is greater than 3
// If username is null, the right side of && will not execute, avoiding null pointer error
if (username != null && username.length > 3) {
print('Valid username');
} else {
print('Username invalid or too short');
}
}
Username is invalid or too short.
Assignment Operators
You are already familiar with the basic assignment operator =.
Dart also provides compound assignment operators to simplify common "compute then assign" operations.
| Operators | Equivalent syntax | Example (when a=10) |
|---|---|---|
| += | a = a + b | a += 3 → 13 |
| -= | a = a - b | a -= 3 → 7 |
| *= | a = a * b | a *= 3 → 30 |
| /= | a = a / b | a /= 2 → 5.0 |
| ~/= | a = a ~/ b | a ~/= 3 → 3 |
| %= | a = a % b | a %= 3 → 1 |
Example
int score = 0;
// Add 10 points for each correct answer
score += 10;
print('Correct answer for question 1: $score');
score += 10;
print('Correct answer for question 2: $score');
// Wrong answer deducts 5 points
score -= 5;
print('Answered 1 question incorrectly: $score');
// Double the score
score *= 2;
print('Reward doubled: $score');
print('EXAMPLE final score: $score');
}
答对第1题: 10 答对第2题: 20 答错1题: 15 奖励翻倍: 30 EXAMPLE 最终得分: 30
Conditional operators: ?? and ??=
These two operators are specifically designed for handling null values and are an important part of Dart's null safety system.
?? null coalescing operator
If the left expression is not null, return its value; otherwise, return the right value.
??= null-aware assignment operator
If the variable is currently null, assign it the value on the right; otherwise, leave it unchanged.
Example
// ?? null coalescing
String? nickname;
String displayName = nickname ?? 'EXAMPLE user';
print(displayName); // EXAMPLE user
nickname = 'Little R';
displayName = nickname ?? 'EXAMPLE user';
print(displayName); // Little R
// Chained ?? also works
String? a;
String? b;
String result = a ?? b ?? 'Default value';
print(result); // Default value
// ??= null-coalescing assignment
int? count;
count ??= 0; // count is null, assign 0
print(count); // 0
count ??= 100; // count is already 0 (non-null), no assignment
print(count); // 0 (unchanged)
}
EXAMPLE 用户 小R 默认值 0 0
Ternary conditional operator ? :
This is Dart's only three-operand operator, a concise version of if-else.
Example
int score = 75;
// Syntax: condition ? value when true : value when false
String result = score >= 60 ? 'Pass' : 'Fail';
print('EXAMPLE exam result: $result');
// Can be nested (but not recommended to exceed two levels; readability will worsen)
String grade = score >= 90 ? 'Excellent' : score >= 60 ? 'Pass' : 'Fail';
print('Rating: $grade');
}
EXAMPLE 考试结果: 及格 评级: 及格
Type checking operators: is and as
is is used to check whether an object belongs to a type, as is used for type casting.
Example
// is: type check
var name = 'EXAMPLE';
print('Is name a String? ${name is String}'); // true
print('Is name an int? ${name is int}'); // false
// is!: not some type
print('Is name not an int? ${name is! int}'); // true
// as: type cast
Object obj = 'Hello, Dart!';
// Cast Object type to String to use String methods
String str = obj as String;
print(str.toUpperCase());
// Safe type check + conversion
Object maybeString = 42;
if (maybeString is String) {
// In a branch where the is check is true, the variable is automatically “promoted” to that type
print(maybeString.length); // No as conversion needed
} else {
print('Not a string, value is: $maybeString');
}
}
name 是 String 吗? true name 是 int 吗? false name 不是 int 吗? true HELLO, DART! 不是字符串,值是: 42
Prefer using is for type checking. In a condition branch where is evaluates to true, Dart automatically promotes the variable to the target type (Type Promotion), so there is no need to use as for casting. Use as only when you are certain of the type but the compiler cannot infer it.
Operator precedence overview
When an expression contains multiple operators, Dart evaluates them in order of precedence from highest to lowest.
If you are unsure about precedence, the safest practice is toUse parentheses to clarify computation order。
| Precedence | Operators | Description |
|---|---|---|
| Highest | () [] . ?. | Parentheses, subscripts, member access |
| ! ~ - ++ -- | Unary operators | |
| * / % ~/ | Multiplication, division, and remainder | |
| + - | Additive | |
| < <= > >= | Relational comparison | |
| == != | Equality check | |
| && | Logical AND | |
| || | Logical OR | |
| ?? | Null coalescing | |
| ? : | Ternary conditional | |
| = += -= *= etc. | Assignment (lowest precedence) |
Example
// Don't rely on precedence—use parentheses to make your intent clear.
int result = ((10 + 5) * 2) - (8 ~/ 3);
print('Calculation result: $result'); // 28
// Without parentheses, the result may be completely different.
// 10 + 5 * 2 - 8 ~/ 3 will be 18 (multiplication and division before addition and subtraction)
int result2 = 10 + 5 * 2 - 8 ~/ 3;
print('Without parentheses: $result2'); // 18
}
计算结果: 28 不加括号: 18other extensions