Dart Variables and Data Types

Variables are the basic units for storing data in a program, and data types determine what values a variable can store.

This chapter introduces variable declaration methods, basic data types, and the important null safety mechanism in Dart.


Variable declaration methods: var, final, const

Dart provides three keywords for declaring variables, each suited to different scenarios.

Understanding their differences is the first step to learning Dart well.

var — Type-Inferred Variables

Variables declared with var have their types automatically inferred from the initial value, and once the type is determined, it cannot be changed.

Example

void main() {
  // Type inference: name's type is inferred as String
  var name = 'EXAMPLE';

  // Type inference: age's type is inferred as int
  var age = 10;

  print('$name is already $age years old');

  // The following code will cause an error—once the type is determined, you cannot assign a value of another type
  // name = 123; // Error: cannot assign int to String
}
EXAMPLE 已经 10 年了

var is not "untyped" or "dynamic"; its type is fixed at the moment of assignment. This is completely different from var in JavaScript.

final — runtime constant

Variables declared with final can only be assigned once, but the timing of assignment can be delayed until runtime.

Example

void main() {
  // final variable: once assigned, cannot be modified
  final currentTime = DateTime.now();
  print('Current time: $currentTime');

  // Delayed assignment is also allowed
  final String greeting;
  greeting = 'Hello, EXAMPLE!';  // First assignment OK
  // greeting = 'Hello again'; // Error: final variable cannot be reassigned

  print(greeting);
}
当前时间: 2026-06-12 10:30:00.000
Hello, EXAMPLE!

const — Compile-time Constants

const is stricter than final: its value must be determinable at compile time.

Example

void main() {
  // const must be determined at compile time
  const siteName = 'EXAMPLE';
  const maxUsers = 100;

  print('Site: $siteName, maximum users: $maxUsers');

  // The following will cause an error: DateTime.now() is a value that can only be determined at runtime
  // const currentTime = DateTime.now(); // Error!
}
站点: EXAMPLE, 最大用户数: 100

Comparison summary of the three

KeywordsModifiableAssignment timingTypical scenarios
varYesAnyRegular variables whose values can change
finalNot modifiableRuntimeConfiguration fetched from an API, the current time.
constNot modifiableCompile-timeMathematical constants, fixed configurations, color values

A practical suggestion: use final by default. When you find you need to modify it, change it to var. This habit makes code safer and reduces bugs caused by accidental modifications.


Numeric types: int and double

Dart's numeric types are divided into two kinds: int (integer) and double (floating-point number).

Their common parent class is num.

Example

void main() {
  // int: integer, range is -2^63 to 2^63-1
  int viewCount = 10000;
  int negativeNumber = -42;

  // double: double-precision floating point number
  double price = 9.99;
  double pi = 3.1415926;

  // num can accept both int and double
  num someNumber = 10;
  someNumber = 10.5;  // Valid

  print(View count: $viewCount);
  print(Price: ¥$price);
  print('Pi: $pi');
}
浏览次数: 10000
Price: ¥9.99
圆周率: 3.1415926

Common methods for numbers

Example

import 'dart:math';  // Import math library

void main() {
  int a = -10;
  double b = 3.7;

  // Absolute value
  print(Absolute value of a: ${a.abs()});   // 10

  // Round to the nearest integer
  print(b rounded: ${b.round()});  // 4

  // Round down
  print(b floor: ${b.floor()});  // 3

  // Round up
  print(b ceil: ${b.ceil()});   // 4

  // Convert string to number
  int parsed = int.parse('42');
  double parsedDouble = double.parse('3.14');
  print(Parsed result: $parsed, $parsedDouble);

  // Generate random number (requires import 'dart:math')
  var random = Random().nextInt(100);
  print(Random number (0-99): $random);
}
a 的绝对值: 10
b 四舍五入: 4
b 向下取整: 3
b 向上取整: 4
解析结果: 42, 3.14
随机数(0-99): 67

String: String and interpolation syntax.

String is used to represent text. Dart strings support both single and double quotes.

String Interpolation is one of the most convenient features in Dart.

Example

void main() {
  // Strings can use single or double quotes
  String singleQuoted = 'Hello';
  String doubleQuoted = "World";

  // Multi-line strings: use triple quotes
  String multiLine = '''
This is the first line
This is the second line
This is the third line - EXAMPLE
  '
'';

  // String interpolation: use $variableName or ${expression}
  String site = 'EXAMPLE';
  int years = 10;

  // $variableName: directly reference variable
  print(Welcome to $site);

  // ${expression}: embed complex expressions
  print($site has been with us for ${years + 1} years);

  // Escape characters
  print('Newline character: first line\nsecond line');
  print('Tab: Column 1\tcolumn 2');
}
欢迎来到 EXAMPLE
EXAMPLE 已经陪伴我们 11 年了
换行符: 第一行
第二行
制表符: 列1    列2

Common methods for strings

Example

void main() {
  String text = '  Hello, EXAMPLE!  ';

  // Remove leading and trailing spaces
  print('trim: [${text.trim()}]');

  // Convert to uppercase / lowercase
  print('Uppercase: ${text.toUpperCase()}');
  print('Lowercase: ${text.toLowerCase()}');

  // Whether it contains a substring
  print('Contains EXAMPLE? ${text.contains('EXAMPLE')}');

  // Whether it starts/ends with a certain string
  print(Starts with a space? ${text.startsWith(' ')}');
  print('Ends with !? ${text.trim().endsWith('!')}');

  // String replacement
  print(Replace: ${text.replaceAll(EXAMPLE', 'DART')}');

  // String splitting
  String csv = 'Dart,Flutter,Google';
  List<String> items = csv.split(',');
  print(Split result: $items);

  // String concatenation
  print(Concatenation: + 'Hello' + ', ' + 'World');
}
trim: [Hello, EXAMPLE!]
大写:   HELLO, EXAMPLE!
小写:   hello, example!
包含 EXAMPLE? true
以空格开头? true
以!结尾? true
替换:   Hello, DART!
分割结果: [Dart, Flutter, Google]
拼接: Hello, World

Boolean value bool

The bool type has only two values: true and false.

It is mainly used for conditional judgments, together with if statements.

Example

void main() {
  bool isLoggedIn = true;
  bool hasPermission = false;

  // Boolean expression
  bool canAccess = isLoggedIn && hasPermission;  // AND: both are true
  bool isGuest = !isLoggedIn;                    // NOT: negate

  print(Can access: $canAccess);
  print(Is guest: $isGuest);

  // Comparison operations produce bool values
  int age = 20;
  bool isAdult = age >= 18;
  print(Is adult: $isAdult);

  // Used directly for condition evaluation
  if (isAdult) {
    print(Welcome to EXAMPLE);
  }
}
可以访问: false
是访客: false
是否成年: true
欢迎访问 EXAMPLE

Dart is a strongly typed language, and conditional judgments only accept the bool type. This is different from JavaScript—in Dart, writing things like if(0) or if('') will directly cause an error.


Null Safety

Null safety is the most important feature introduced in Dart 2.12.

Its core idea is: by default, all variables cannot be null, unless you explicitly declare it.

Nullable and Non-nullable Types

Adding ? after the type indicates that the variable can be null.

Example

void main() {
  // Non-null type: cannot assign null
  String name = 'EXAMPLE';
  // name = null; // Error! name cannot be null

  // Nullable type: allowed to be null
  String? nickname;
  nickname = null;  // OK
  nickname = 'R';   // Also OK

  print('Nickname: $nickname');

  // int? can also be null
  int? score;
  print('Score: $score');  // Outputs null
}
昵称: R
分数: null

Null-handling operator

ManipulatorsDescriptionExample
??If the left side is null, use the right side value.name ?? 'default name'
??=If the variable is null, assign the right side value.name ??= 'default name'
?.Safe access: skip the call when the object is null.user?.name
!Assert non-null (use with caution)name!

Example

void main() {
  String? username;

  // ?? operator: if username is null, use default value
  String displayName = username ?? 'EXAMPLE Visitor';
  print(displayName);  // EXAMPLE Visitor

  // ??= operator: if null, assign value
  username ??= 'New user';
  print(username);  // New user

  // ?. safe access: only call when non-null
  String? maybeNull;
  print(maybeNull?.length);  // null (no error)

  maybeNull = 'Hello';
  print(maybeNull?.length);  // 5

  // ! Assertion: I am sure it is not null (throws exception when null)
  String definitelyNotNull = 'EXAMPLE';
  print(definitelyNotNull!.length);  // 6
}
EXAMPLE 访客
新用户
null
5
6

Try to avoid using the ! assertion operator. If you use ! frequently, it indicates a possible problem with your type design. Prefer using ??, ??=, and ?. to handle null values safely.


Type conversion

In Dart, values of different types can be converted to each other.

Example

void main() {
  // Number → String
  int count = 42;
  String countStr = count.toString();
  print('Number to string: $countStr (type: ${countStr.runtimeType})');

  // String → Number
  String priceStr = '19.99';
  double price = double.parse(priceStr);
  print('String to number: ¥$price');

  // int &#x2194; double
  int integer = 10;
  double decimal = integer.toDouble();
  print(int to double: $decimal);

  double pi = 3.14;
  int piInt = pi.toInt();  // Truncate the fractional part
  print(double to int (truncated): $piInt);

  // Any value → string
  bool flag = true;
  print(bool to string: ${flag.toString()});

  // String → bool (requires manual judgment)
  String boolStr = 'true';
  bool parsed = boolStr == 'true';
  print(String to bool: $parsed);
}
数字转字符串: 42 (类型: String)
字符串转数字: ¥19.99
int 转 double: 10.0
double 转 int (截断): 3
bool 转字符串: true
字符串转 bool: true
other extensions