?
연산자 (Null-aware 연산자)?.
은 null이 아닌 경우에만 속성이나 메서드에 접근합니다. 만약 변수가 null
이라면 연산이 중단되고 결과는 null
이 된다.String? name;
int length = name?.length ?? 0;
위 코드에서 name
이 null
이라면 length
는 0이 된다.??
??
연산자는 null이 아닌 경우에는 왼쪽 피연산자를 반환하고, null인 경우에는 오른쪽 피연산자를 반환한다.
String? name;
String displayName = name ?? 'Guest';
위 코드에서 name
이 null
이라면 displayName
은 'Guest'가 된다.??
연산자를 사용할 때, 왼쪽 피연산자가 null이 아닌 경우에만 오른쪽 피연산자는 계산되지 않는다.
?? 연산자를 이용하면 왼쪽 값이 null인지 체크해서 null이 아니면 왼쪽 값을 리턴하고 null이면 오른쪽 값을 리턴한다.
??(QQ)의 뜻은 만약 왼쪽의 있는 값이 Null이라면 오른쪽 값을 return 시킨다는 것이다.
쉽게 말해서 위 코드를 보면 name.toUpperCase()를 리턴할 것이다.
그런데 만약 name이 null이여서 toUpperCase()를 실행할 수 없다면 "NONE"을 리턴하는 것이다.
name에 ?(옵셔널)을 붙인 이유는 name이 null일 수도 있기 때문이다.
?? 연산자는 flutter에서 자주 사용된다.
void main() {
// null
double? number = 4.0;
print(number);
number = 2.0;
print(number);
number = null;
print(number);
number ?? = 3.0; // number가 Null이라면 오른쪽 값으로 바꿔라, Null이 아니라면 바꾸지 않는다
print(number);
}
const x = null;
const y = 1;
const z = 2;
print(x ?? y); // 1, 우측 y값 선택
print(y ?? x); // 1, 좌측 y값 선택
print(y ?? z); // 1, 둘다 null이 아니지만 좌측 y값 선택
플러터에서 이용 사례
_image ?? const Text('No Image')
??=
const x = null;
const y = 1;
var t;
t ??= x; // t가 null이면 x를 대입하는데 x도 null이다.
print(t); // null
t ??= y; // t가 null이면 y를 대입한다.
print(t); // 1
t ??= x; // t가 null이면 x를 대입하는데 null이 아니므로 x를 대입하지 않는다.
print(t); // 1
?.
x
객체가 null이 아닐 때에만 속성과 메소드에 접근한다.
x?.foo();
x?.bar
...?
const a = [
...[1, 2],
null,
];
위 결과는 [1, 2, null]
이며 끝에 null이 아닌 [1, 2]
가 필요하다면 아래와 같이 작성한다.
var list = [
...[1, 2],
...?newList,
];
하지만 아래 경우에는 null이 아닌 원소만 추가할 때는 if
구문으로 작성할 수 밖에 없다.
var list = [
1,
2,
if (elem() != null) elem(),
];
!
non-null 단언 연산자(non-null assertion operator)null
일 가능성이 없다고 확신하는 경우 사용한다.!
를 남발하면서 사용하는 것은 프로그램의 안정성을 저해할 수 있다.?
를 붙여 주면 해당 변수는 해당 타입 또는 null
이 될 수 있다.String? name;
위와 같이 선언하면 초기화하지 않아도 에러가 발생하지 않는다.?
를 붙여 name
변수에 이제 Null 값을 넣어도 좋다고 컴파일러한테 허락을 받았다.!
를 붙여 컴파일러에게 Null이 아님을 주장하고 변수를 사용했다.int? age = 1;
age = age! + 1;
!
를 붙여 명시적으로 해당 변수는 Null
이 아님을 표시한다.?
를 붙이지 않고 선언하는 방법이 있다.required
를 붙여서 인스턴스 생성할 때 매개변수로 값을 넘겨 받는다고 약속해주는 것이다.class Person {
String name; // ? 없이 초기화 하지 않고 변수 선언
int age;
String? address;
Person({required this.name, required this.age, this.address});
}
required
외에 추가로 late
키워드가 있다.late
변수는 널 확인 검사를 할 수 없다.void main() {
late final String name;
// do something, go to api
name = 'shin';
print(name);
// data fetching할때 유용
}
class Person {
late String name;
late int age;
void initState() {
super.initState();
name = 'pincoin'; // late 변수는 반드시 `initState()` 메소드 안에서 초기화해준다.
age = 40; // 초기화
}
}
late
변수는 initState()
메소드에서 초기화하고 사용할 때는 null 확인 검사를 하지 않는다.late
변수를 널인지 확인한다고 하면 오류를 낸다.late
변수는 절대 null이 아님을 논리적인 코드를 통해 보장해야 한다.late String name;
이 아니라 String? name;
으로 선언한다.