# Null이 될 수 있는 타입
- 코틀린에는 널이 될 수 있는 타입이 따로 존재하며 명시적으로 타입 뒤에 '?'를 붙여 사용한다 ex)String?
- 모든 타입은 기본적으로 Non- Null Type 이라는 의미
- Nullable Type일 경우 변수.메소드()처럼 사용할 수 없다
- Non-Null Type에 null도, nullable 타입도 대입할 수 없으며, 함수의 파라미터에도 마찬가지
- Nullable Type을 일단 널 체크 하고 나면, Non-Null Type처럼 사용할 수 있다
- 이렇게 컴파일 시점 NullPointException이 발생할 가능성을 체크해서 Null Safety를 보장할 수 있다
- 모든 검사는 컴파일 시점에 수행되므로, Nullable/Non-Null 타입 처리 관련해서 실행시점에 추가적인 부가 비용은 없다
# Safe Call Operator ?.
- null 체크와 메소드 호출을 한번에 수행한다
- 호출하려는 값이 null이 아니면 메소드가 호출 된다
- 호출하려는 값이 null이면 메소드 호출은 무시되고 결과값은 null 이 된다
- 객체 안에 객체가 여럿 있다면 한 식 안에서 ?. 를 이용해 사용하기가 편한 경우가 있다
class ClassType(val classNm: String?) class Subject(val className: String, val classType: ClassType?) class Student(val name: String, val subject: Subject?) //1)기존 방식 fun Student.getClassType(): String? { if (this.subject != null) { if (this.subject.classType != null) { return this.subject.classType.classNm } } return "" } //2)Safe Call 사용 방식 fun Student.getClassType2(): String? = this.subject?.classType?.classNm
# 엘비스 연산자 ?:
- null 대신 사용할 디폴트 값을 지정할 때 편리하게 사용할 수 있는 연산자 이다
- 위의 Safe Call Operator 예제에서 Student.getClassType2( )의 리턴값이 Nullable이었는데, 이 때 null을 대신할 기본값을 엘비스 연산자를 이용해 아래와 같이 사용할 수 있다(리턴값을 Non-Null로 설정한 것을 볼 수 있다)
fun Student.getClassType2(): String = this.subject?.classType?.classNm ?: "No classNm"
- 코틀린에서는 return이나 throw도 '식'이라서 엘비스 연산자의 우항에 넣을 수가 있다. 즉, 좌항이 null일 경우 바로 어떤값을 return 하고나 예외를 throw 할 수 있다
-
//1. 우항에 return 처리 fun Student.getClassType(): String { this.subject ?: return "No subject" this.subject.classType ?: return "No classType" return this.subject.classType.classNm ?: "No classNm" } //2. 우항에 exception throw 처리 fun Student.getClassType3(): String =this.subject?.classType?.classNm ?: throw IllegalStateException("No classNm")
# 안전한 캐스트 as?
- 코틀린에서 캐스트 연산은 as로 하는데, 캐스팅 불가 타입일 경우 ClassCastException이 발생한다
- 그럼 as 연산을 할 때마다 미리 is를 통해 변환 가능한지 검사해 봐야 하느냐? -> 그러지 말고 as? 를 사용하면 캐스팅 불가 타입일 경우 null을 반환한다
- 불가 타입일 경우 null이 반환 되므로, 뒤에 엘비스 연산자와 함께 유용하게 쓰인다
아래 예제에서 어떤 구문이 출력 될지 생각해 보자
class Subject(val className: String, val classType: ClassType?)
open class Student(val name: String, val subject: Subject?)
class HighSchoolStudent(val grade: Int, name: String, subject: Subject?) :
Student(name, subject)
fun saveCast(highSchoolStudent: HighSchoolStudent, subject: Subject){
highSchoolStudent as? Student ?: println("highSchoolStudent is Not Student") //1번
subject as? Student ?: println("subject is Not Student") //2번
}
1번은 캐스팅 될 것이므로 print 되지 않고, 2번 구문이 print 될 것이다
잘못된 내용이나 궁금한 내용 있으시면 댓글 달아주세요
좋은 하루 되세요!
출처 : Kotlin In Action - 에이콘 출판사
(위 도서를 학습하고 개인 학습용으로 정리한 내용입니다)
'Kotlin' 카테고리의 다른 글
[Kotlin] Java 컬렉션 Kotlin에서 사용하기, Kotlin 배열 (0) | 2021.12.28 |
---|---|
[Kotlin] 5. Not-null assertion, let 함수, lateinit (0) | 2021.12.15 |
[Kotlin] CoRoutines (0) | 2021.12.07 |
[Kotlin] 4. 람다 - with/apply (1) | 2021.12.05 |
[Kotlin] 4.람다 - 함수형 인터페이스(SAM 인터페이스) (0) | 2021.12.04 |