Operators in Dart tutorial explains Dart operators. We show how to use operators to create expressions.
last modified June 4, 2025
This tutorial explores Dart operators, demonstrating how they are used to create expressions for processing data.
An operator is a symbol that triggers a specific operation on its operands. Inspired by mathematics, operators in programming manipulate data. An operand is an input to an operator, typically a value or variable.
Expressions combine operands and operators, with the operators defining the operations to perform. The evaluation order is governed by operator precedence and associativity, ensuring predictable results.
Operators are classified by the number of operands they take. Unary operators use one operand, while binary operators use two. Some operators, like +, are overloaded, performing different tasks (e.g., adding numbers or concatenating strings) based on context.
The minus sign operator - negates a value, reversing its sign.
main.dart
void main() { int a = 1;
print(-a); print(-(-a)); }
This example shows the minus sign operator negating a value and then reversing it back to its original sign.
$ dart main.dart -1 1
The assignment operator = stores a value in a variable. Unlike in mathematics, where = denotes equality, in programming it assigns the right-side value to the left-side variable.
int x = 1;
This assigns the value 1 to the variable x.
x = x + 1;
This increments x by 1, resulting in x equaling 2. Such expressions are valid in programming but not in mathematics.
3 = x;
This is invalid, as literals like 3 cannot be assigned values, causing a syntax error.
Dart’s null-aware assignment operator ??= assigns a value to a variable only if it is null, ensuring safe initialization.
main.dart
void main() { int? x; x ??= 6; print(x);
x ??= 3; print(x); }
Since x is initially null, 6 is assigned. The second assignment is ignored because x is no longer null.
$ dart main.dart 6 6
The increment (++) and decrement (–) operators add or subtract 1 from a variable, offering a concise way to update values.
main.dart
void main() { var x = 6;
x++; x++;
print(x);
x–; print(x); }
This example increments x twice from 6 to 8, then decrements it to 7, demonstrating both operators.
$ dart main.dart 8 7
These operators can be prefix or postfix, affecting when the value is updated relative to its use, which may lead to subtle differences in behavior.
main.dart
void main() { var r1 = increase(3); print(r1);
var r2 = increase2(3); print(r2); }
int increase(int x) { return ++x; }
int increase2(int x) { return x++; }
The prefix ++x increments before returning, yielding 4. The postfix x++ returns the original value before incrementing, yielding 3.
$ dart main.dart 4 3
Compound assignment operators combine an operation with assignment, providing a shorthand for common updates like addition or multiplication.
a = a + 3; a += 3;
Both expressions add 3 to a, with += being the shorthand form. Other compound operators include -=, *=, /=, ~/=, %=, &=, |=, ^=, <<=, and >>=.
main.dart
void main() { var a = 1; a = a + 1; print(a);
a += 5; print(a);
a *= 3; print(a); }
This example shows standard addition, followed by compound addition and multiplication, resulting in a being updated to 2, 7, and 21.
$ dart main.dart 2 7 21
Arithmetic operators perform mathematical operations on numeric operands, including addition, subtraction, multiplication, and division.
SymbolName +Addition -Subtraction *Multiplication /Division ~/Integer division %Remainder
The table above lists the arithmetic operators in Dart
main.dart
void main() { var a = 10; var b = 11; var c = 12; var add = a + b + c; var sb = c - a; var mult = a * b; var div = c / 3; var rem = c % a;
print(add); print(sb); print(mult); print(div); print(rem); }
This example demonstrates addition, subtraction, multiplication, division, and remainder operations, with % computing the modulo (e.g., 12 % 10 = 2).
$ dart main.dart 33 2 110 4.0 2
The / operator returns a double, while ~/ returns an integer, distinguishing floating-point and integer division.
main.dart
void main() { var c = 5 / 2; print(c);
var d = 5 ~/ 2; print(d); }
This shows / returning 2.5 (double) and ~/ returning 2 (integer) for 5 divided by 2.
$ dart main.dart 2.5 2
Boolean operators, also called logical operators, manipulate boolean values to control program flow, often in conditional statements.
SymbolName &&Logical AND ||Logical OR !Negation
The table above lists the boolean operators in Dart.
main.dart
void main() { var x = 3; var y = 8;
print(x == y); print(y > x);
if (y > x) { print(“y is greater than x”); } }
This example uses comparison operators to produce boolean results, which drive an if statement, printing a message when true.
$ dart main.dart false true y is greater than x
The logical AND (&&) operator returns true only if both operands are true.
main.dart
void main() { var a = true && true; var b = true && false; var c = false && true; var d = false && false;
print(a); print(b); print(c); print(d); }
This demonstrates &&, with only the first case yielding true.
$ dart main.dart true false false false
The logical OR (||) operator returns true if at least one operand is true.
main.dart
void main() { var a = true || true; var b = true || false; var c = false || true; var d = false || false;
print(a); print(b); print(c); print(d); }
Three of the four cases yield true, as only both false operands result in false.
$ dart main.dart true true true false
The negation operator ! inverts a boolean value.
main.dart
void main() { print(!true); print(!false); print(!(4 < 3)); }
This shows ! flipping true to false and evaluating an expression to true.
$ dart main.dart false true true
Comparison operators, also known as relational operators, compare values and return a boolean result, essential for decision-making in code.
SymbolMeaning <Less than <=Less than or equal to >Greater than >=Greater than or equal to ==Equal to !=Not equal to
The table above lists the comparison operators in Dart.
main.dart
void main() { print(3 < 4); print(3 == 4); print(4 >= 3); print(4 != 3); }
This example compares integers using == for equality (unlike some languages that use =), yielding boolean results.
$ dart main.dart true false true true
Bitwise operators manipulate binary representations of numbers, performing bit-by-bit operations, useful for low-level tasks like flag management.
SymbolMeaning &Bitwise AND |Bitwise OR ^Bitwise XOR ~Bitwise NOT <<Left shift >>Right shift
The bitwise AND (&) yields 1 only when both corresponding bits are 1.
00110
& 00011 = 00010
For 6 (00110) and 3 (00011), the result is 2 (00010).
main.dart
void main() { print(6 & 3); }
$ dart main.dart
2
The bitwise OR (|) yields 1 if either bit is 1.
00110
| 00011 = 00111
For 6 and 3, the result is 7 (00111).
main.dart
void main() { print(6 | 3); }
$ dart main.dart
7
The bitwise XOR (^) yields 1 if exactly one bit is 1.
00110
^ 00011 = 00101
For 6 and 3, the result is 5 (00101).
main.dart
void main() { print(6 ^ 3); }
$ dart main.dart
5
The ternary operator ?: provides a concise conditional expression, evaluating one of two expressions based on a boolean condition.
condition ? expr1 : expr2
If the condition is true, expr1 is evaluated; otherwise, expr2 is evaluated.
main.dart
void main() { var age = 18;
var isAdult = (age >= 18) ? true : false;
if (isAdult) { print(“he is adult”); } else { print(“he is minor”); } }
This uses the ternary operator to set isAdult based on age, then prints a message using an if statement.
$ dart main.dart he is adult
The spread operator … inserts all elements of a collection into another, simplifying list, set, or map construction.
main.dart
void main() { var vals = [1, 2, 3]; var vals2 = […vals, 4, 5, 6];
print(vals); print(vals2); }
This expands vals into vals2, adding more elements to create a new list.
$ dart main.dart [1, 2, 3] [1, 2, 3, 4, 5, 6]
The cascade operator .. allows multiple operations on the same object, enhancing code fluency and readability.
main.dart
class User { var fname; var lname; var occupation; String toString() { return “$fname $lname is a $occupation”; } }
void main() { var u = User() ..fname = “John” ..lname = “Doe” ..occupation = “gardener”;
print(u); }
This initializes a User object’s properties using cascades, then prints its string representation.
$ dart main.dart John Doe is a gardener
The is and is! operators check an object’s type at runtime, returning true if the type matches or does not match, respectively.
main.dart
class Base {}
class Derived extends Base {}
void main() { var b = Base(); var d = Derived();
print(d is Base); print(d is! Base); print(b is Derived); print(d is Object); print(d is! Object); }
This checks type relationships, showing inheritance and object type properties.
$ dart main.dart true false false true false
Dart’s null-aware operators, like ?? and ??=, handle null values safely, providing defaults or conditional assignments to prevent null-related errors.
main.dart
void main() { String? name;
// Null-coalescing operator String displayName = name ?? “Guest”; print(displayName);
// Null-aware assignment name ??= “Anonymous”; print(name);
name ??= “User”; print(name); }
The ?? operator provides a default if name is null, while ??= assigns a value only if the variable is null, leaving it unchanged otherwise.
$ dart main.dart Guest Anonymous Anonymous
The conditional member access operator ?. safely accesses properties or methods of an object, returning null if the object is null, avoiding runtime errors.
main.dart
void main() { String? text;
// Conditional member access int? length = text?.length; print(length);
text = “Hello”; length = text?.length; print(length); }
This safely accesses the length property, returning null when text is null and the actual length when non-null.
$ dart main.dart null 5
The type cast operator as converts an object to a specific type at runtime, throwing an exception if the cast is invalid, useful for working with dynamic or interface types.
main.dart
void main() { var value = “Dart”;
// Type cast String text = value as String; print(text.toUpperCase());
// Safe cast with is check if (value is String) { String safeText = value as String; print(safeText.length); } }
This casts value to a String, allowing String-specific operations, and demonstrates a safe cast with a type check.
$ dart main.dart DART 4
Operator precedence determines the order in which operators are evaluated, resolving ambiguities in expressions to ensure consistent results.
main.dart
void main() { print(3 + 5 * 6); print((3 + 5) * 6);
print(!true || true); print(!(true || true)); }
Multiplication has higher precedence than addition, so 5 * 6 is evaluated first, yielding 33. Parentheses override this, yielding 48. Negation precedes ||, affecting logical outcomes.
$ dart main.dart 33 48 true false
The following table lists the operator precedence in Dart, from highest to lowest. Operators with higher precedence are evaluated before those with lower precedence. Operators on the same row have equal precedence and are evaluated according to associativity rules.
PrecedenceOperator(s)Description
1 (highest)[], (), ., ?.Member access, function call 2++, –, ~Postfix increment/decrement, bitwise NOT 3++, –, +, -, !Prefix increment/decrement, unary plus/minus, logical NOT 4*, /, %, ~/Multiplicative 5+, -Additive 6>>, <<Bitwise shift 7>, <, >=, <=, is, is!Relational, type test 8==, !=Equality 9&Bitwise AND 10^Bitwise XOR 11|Bitwise OR 12&&Logical AND 13||Logical OR 14??Null-coalescing 15? :Conditional (ternary) 16=, +=, -=, *=, /=, %=, ~/=, &=, |=, ^=, <<=, >>=, ??=Assignment 17 (lowest),Comma
Refer to this table to understand how Dart evaluates complex expressions and to avoid unexpected results due to operator precedence.
Associativity determines the evaluation order for operators with equal precedence. Most operators, like / and *, are left-to-right, while assignment and unary operators are right-to-left.
main.dart
void main() { print(9 / 3 * 3);
var j = 0; j *= 3 + 1; print(j); }
The expression 9 / 3 * 3 evaluates left-to-right as (9 / 3) * 3, yielding 9. The compound assignment *= is right-to-left, so 3 + 1 is evaluated first, then multiplied by j.
$ dart main.dart 9.0 0
Dart operators - language reference
This tutorial covered Dart operators, their roles in expressions, and how precedence and associativity shape evaluation.
My name is Jan Bodnar, a passionate programmer with extensive experience. Since 2007, I have authored over 1,400 articles and 8 e-books, with more than ten years of teaching programming.
List all Dart tutorials.