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

void main() {
  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

void main() {
  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.

OperatorsMeaningExampleResult
==equals5 == 5true
!=Not equal5 != 3true
>greater than5 > 3true
<less than5 < 3false
>=greater than or equal to5 >= 5true
<=less than or equal to3 <= 5true

Example

void main() {
  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.

OperatorsMeaningDescription
&&Logical ANDReturns true only if both sides are true.
||Logical ORReturns true if either side is true.
!Logical NOTNegation: true becomes false, false becomes true

Example

void main() {
  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:

void main() {
  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.

OperatorsEquivalent syntaxExample (when a=10)
+=a = a + ba += 3 → 13
-=a = a - ba -= 3 → 7
*=a = a * ba *= 3 → 30
/=a = a / ba /= 2 → 5.0
~/=a = a ~/ ba ~/= 3 → 3
%=a = a % ba %= 3 → 1

Example

void main() {
  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

void main() {
  // ?? 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

void main() {
  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

void main() {
  // 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。

PrecedenceOperatorsDescription
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

void main() {
  // 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
不加括号: 18
other extensions