반응형
6.1 널 가능성
- NPE : null pointer exception
- 코틀린은 Nullability로 NPE를 피할 수 있게 해준다
6.1.1 널이 될 수 있는 타입
- 코틀린은 java와 다르게 null 이 될 수 있는 타입을 명시적으로 지원한다
- 모든 타입은 기본적으로 널이 될 수 없는 타입이다
- ?가 붙어야 널이 될 수 있다
- 널이 될 수 있는 타입의 변수인 경우 수행할 수 있는 연산이 제한된다
- 변수.메소드() 형식이 제한된다
- ?. !! 등을 써줘야 한다
- 널이 될 수 있는 값을 널이 될 수 없는 타입의 변수에 대입할 수 없다
- 널이 될 수 있는 타입의 값을 널이 될 수 없는 타입의 파라미터를 받는 함수에 전달할 수 없다
- 변수.메소드() 형식이 제한된다
- null과 널이 될 수 있는 변수를 비교한 다음에는
- 위의 제한 되는 부분들이 모두 풀리고 컴파일 가능해진다
- 비교할때는 if 문을 수행할수도있고 다양한 도구가 있다
6.1.2 타입의 의미
- kotlin에서는 null이 될 수 있는 값과, 될 수 없는 값을 구분해서 각각이 가능한 연산을 명확히 정해둠
- 실행 시점에 예외를 발생시킬 수 있는 연산을 판단하여 아예 금지시킨다
- null이 될 수 있는 타입과 널이 될 수 없는 타입의 객체는 같다
- 널이 될 수 있는 타입은 널이 될 수 없는 타입을 감싼 래퍼타입이 아니다
- 컴파일 시점에 검사를 수행
- 그래서 kotlin에서 널이 될 수 있는 타입을 처리할 때 별도의 부가비용이 들지 않는다
6.1.3 안전한 호출 연산자 : ?.
- ?.
- null 검사와 메소드 호출
s?.toUpperCase() if(s!=null) s.toUpperCase() else null
- null 검사와 메소드 호출
- 아래 식처럼 써야 하는 것을 ?. 로 간단하게 표현 가능
- ?. 의 결과값도 null이 될 수 있다
String.toUpperCase
는 String을 리턴String?.toUpperCase
는 String?을 리턴- 메소드 호출 뿐만 아니라 property를 읽고 쓸때도 ?. 사용 가능
- ?. 연쇄해서 사용하면 한줄로 정리 가능
6.1.4 엘비스 연산자 : ?:
- null 대신 사용할 default 값을 지정할 때 사용하는 연산자
- 이항 연산자
- 좌항을 계산한 값이 널인지 계산
6.1.5 안전한 캐스트 : as?
- as 로 타입을 바꿀 수 없으면 ClassCastException이 발생한다
- as?
- 대상 타입으로 변환할 수 없으면 null을 반환한다
6.1.6 널 아님 단언 : !!
- not null assertion
- 널에 !!를 적용하면 NPE가 발생한다
person.company!!.address!!.country
- !! 를 널에 대해서 사용해서 바생하는 예외의 stack trace에는 어떤 파일의 몇번째 줄인지에 대한 정보가 들어있다
- 어떤 식에서 예외가 발생했는지는 들어있지 않기 때문에 한줄에 중첩해서 사용하는 것 지양
6.1.7 let 함수
- 안전한 호출 연산자와 함께 let을 사용하면 원하는 식을 평가해서 결과가 널인지 검사한 다음에 그 결과를 변수에 넣는 작업을 처리
- 널이 될 수 있는 값을 널이 아닌 값만 인자로 받는 함수에 넘기기
fun sendEmailTo(email : String){~~} // sendEmailTo 함수는 null이 아닌 값만 받는다 // 이 함수에게 널이 될 수 있는 타입의 값을 넘길 수는 없다 if(email != null ) sendEmailTo(email) // 이렇게 검사 후 넘겨주는 방식도 있다 // let 사용하면 email?.let{email -> sendEmailTo(email)} // 더 짧은 방식 email?.let{sendEmailTo(it)}
- let 함수는 email 값이 null이 아닌 경우에만 호출된다
- null 인 경우에는 아무일도 일어나지 않는다
6.1.8 나중에 초기화할 프로퍼티
- lateinit
- 프로퍼티를 나중에 초기화 하는데 사용
- 나중에 초기화 하는 property는 반드시 var 이어야 한다
- val property는 final 필드로 컴파일 되며, 생성자 안에서 반드시 초기화 해야 한다
6.1.9 널이 될 수 있는 타입 확장
- 널이 될 수 있는 타입에 대한 확장함수 정의하면 null을 다루는 도구가 된다
- ?. !! 등의 안전한 호출 없이도 호출 가능하다
6.1.10 타입 파라미터의 널 가능성
fun <T> printHashCode(t:T){
println(t?.hashCode())
}
printHashCode(null)
- T 는 Any? 타입
- 물음표가 붙어있지 않지만 널이 될 수 있는 타입
fun <T : Any> printHashCode(t:T){
println(t.hashCode())
}
- 위와 같이 T:Any 로 지정을 해주면 T는 Any 타입이 된다
- 널이 될 수 없는 타입이 됨
6.1.11 널 가능성과 자바
- java와 kotlin의 상호 운용성
- java 타입 시스템은 널 가능성을 지원하지 않는다
- java 에서는 annotation으로 널 가능성을 표현할 수 있다
- 플랫폼 타입
- kotlin이 널 관련 정보를 알 수 없는 타입
- 자바 api의 경우 대부분 널 관련 애노테이션을 사용하지 않기 때문에 주의해야 한다
val i: Int = person.name
ERROR : Type mismatch : inferred type is String! but Int was expected
- String!
- ! 표기는 String! 타입의 널 가능성에 대해 아무 정보도 없다는 뜻이다
- 상속
- 자바 코드를 상속받아 메소드를 오버라이드 할때
- 널 가능한것, 널 불가능한것으로 모두 구현 가능하다
- 자바 코드를 상속받아 메소드를 오버라이드 할때
반응형
'Languages' 카테고리의 다른 글
kotlin의 null 가능성과 collection (0) | 2020.05.07 |
---|---|
kotlin의 원시타입 (int, boolean, any) (0) | 2020.05.07 |
kotlin의 수신객체 지정 람다 (with, apply) (0) | 2020.04.26 |
java 함수에 kotlin lambda 식 메소드로 전달하기 (자바 함수형 인터페이스) (0) | 2020.04.26 |
kotlin의 lazy evaluation (sequence, map, filter) (0) | 2020.04.26 |