반응형


[Flutter] Dart 널 안전성 및 관련 연산자

(Null Safety) as, late, !, ?., ?[], ??=, ??

 

 

   목차

  1. 널 안전성 (Null Safety)
  2. NonNull vs Nullable
    1. NonNull 변수 
    2. Nullable 변수
  3. 널 안전성 관련 연산자 
    1. as : 형변환 연산자
    2. late : 초기화 지연 연산자
    3. ! : 값을 강제로 할당하는 연산자
    4. ?. : null 안전 접근 연산자
    5. ?[ ] : null 안전 인덱스 연산자
    6. ??= : 왼쪽 변수가 null일 때만 값을 할당하는 연산자
    7. ?? : 왼쪽 값이 null인 경우 오른쪽 값을 사용하는 연산자

 

 

1. 널 안전성 (Null Safety)

 

널 안정성은 변수나 객체가 null이 될 수 있는지 여부를 지정하여 사용함으로써, null 값에 의해 발생되는 에러(ex, NPE - Null Point Exception)를 사전에 방지하는 기능을 말합니다. 

 

 

 

2. NonNull vs Nullable

 

Dart에서 변수를 선언하게 되면 기본적으로 null 값을 허용하지 않는 NonNull 변수가 됩니다. null값을 허용하는 Nullable 변수로 사용하려면 변수 선언시 데이터 타입에 ?를 추가하여 변수 선언을 해야합니다.

 

1) NonNull 변수

  1. NonNull 변수는 null 값을 허용하지 않는 변수를 말합니다.
  2. 일반적인 변수 선언시 NonNull 변수가 됩니다.
  3. NonNull 변수는 반드시 초기화를 해야합니다.
    • Top-level 변수와 class변수 : 변수 선언과 동시에 초기화 해야됩니다.
    • 함수내 지역변수 : 변수 선언과 동시에 초기화를 꼭 해야되는건 아니지만 사용전에는 초기화 해야됩니다.
int a1 = 1;		// 정상
int a2 = null;		// Error
int a3;			// Error

class MyData {
  int b1 = 2;		// 정상
  int b2 = null;	// Error
  int b3;		// Error

  void display() {
    int c1 = 3;		// 정상
    int c2 = null;	// Error
    int c3;		// 정상 (사용전 초기화 해야됨)
  }
}

 

 

2) Nullable 변수

  1. Nullable 변수는 null 값을 허용하는 변수를 말합니다. 
  2. 변수 선언시 데이터 타입에 ?를 추가하여 변수 선언을 합니다.
  3. 초기화 하지 않으면 null 값으로 초기화 됩니다. 
int? a1 = 1;		// 정상
int? a2 = null;	// 정상
int? a3;		// 정상

class MyData {
  int? b1 = 2;		// 정상
  int? b2 = null;	// 정상
  int? b3;		// 정상

  void display() {
    int? c1 = 3;	// 정상
    int? c2 = null;	// 정상
    int? c3;		// 정상 
  }
}

 

 

 

3. 널 안전성 관련 연산자

  1. as : 형변환 연산자 (ex, a = b as int;)
  2. late : 초기화 지연 연산자 (ex, late int a; )
  3. ! : 값을 강제로 할당하는 연산자 (ex, int b = 10 + a!;)
  4. ?. : null 안전 접근 연산자 (ex, int? a_length = a?.length;)
  5. ?[ ] : null 안전 인덱스 연산자 (ex, int? a1 = a?[1];)
  6. ??= : 왼쪽 변수가 null일 때만 값을 할당하는 연산자 (ex, a ??= 100;)
  7. ?? : 왼쪽 값이 null인 경우 오른쪽 값을 사용하는 연산자 (ex, int c = a ?? 999;)

 

1) as : 형변환 연산자

  • 명시적으로 타입을 변환할 때 사용합니다. 
    1. 하위클래스를 상위클래스로 형변환 (업캐스팅) : 자동 형변환 됨
    2. 상위클래스를 하위클래스로 형변환 (다운캐스팅) : 명시적 형변환 필요
    3. NonNull 변수를 Nullable 변수에 대입 할 경우  : 자동 형변환 됨
    4. Nullable 변수를 NonNull 변수에 대입 할 경우 : 명시적 형변환 필요 
int  a = 1;
int? b = 2;

void main() {
  a = b as int;
  b = a;
  
  print("$a, $b");  // 2, 2
}

 

 

2) late : 초기화 지연 연산자

  • 변수의 초기화를 선언과 동시에 하지 않고 나중에 할 수 있도록 해줍니다.
late int a;

void main() {
  a = 1;
  
  print("$a");  // 1
}

 

 

3) ! : 값을 강제로 할당하는 연산자

  • 값이 null이 아님을 개발자가 보증할때 사용하며, null인 경우에는 에러가 발생합니다. (null assertion operator) 
int? a = 1;
int b = 10 + a!;

 

 

4) ?. : null 안전 접근 연산자

  • 객체가 null이 아닌 경우에만 멤버에 접근하며, null인 경우에는 null을 반환합니다. (conditional member access)
String? a = "aaa";
String? b = null;

int? a_length = a?.length;
int? b_length = b?.length;

print("$a_length, $b_length");	// 3, null

 

 

5) ?[ ] : null 안전 인덱스 연산자

  • List 객체가 null이 아닌 경우에만 접근가능하며, null인 경우에는 null을 반환합니다. (conditional subscript access)
List<int>? a = [1, 2, 3];
List<int>? b = null;

int? a1 = a?[1];
int? b1 = b?[1];

print("${a?[0]}, ${b?[0]}");  // 1, null
print("$a1     , $b1     ");  // 2, null

 

 

6) ??= : 왼쪽 변수가 null일 때만 값을 할당하는 연산자

  • 왼쪽 변수의 값이 null인 경우에만 값을 할당하고, 왼쪽 변수의 값이 null 인 경우에는 아무런 변화가 없습니다.
int? a = 1;
int? b = null;
print("[a] $a,  [b] $b");	// [a] 1,  [b] null

a ??= 100;
b ??= 100;
print("[a] $a,  [b] $b");	// [a] 1,  [b] 100

 

 

7) ?? : 왼쪽 값이 null인 경우 오른쪽 값을 사용하는 연산자

  • 대입해야 하는 값이 null인 경우 대체해야 할 default 값을 지정할 때 사용합니다. 
int? a = 10;
int? b = null;

int c = a ?? 999;
int d = b ?? 999;

print("[c] $c,  [d] $d");	// [c] 10,  [d] 999

 

반응형
반응형

+ Recent posts