2장 코틀린 기초
2.1 코틀린에서 널 허용 타입 사용하기
이슈: 변수가 절대 널(null) 값을 갖지 못하게 하고 싶다.
해법: 물표를 사용하 않고 변수의 타입을 정의한다. 또한 널 허용(nullable) 타입은 안전 호출 연산자(?.)나 엘비스 연산자(?:)와 결합해서 사용한다.
코틀린의 가장 매력적인 기능은 가능한 모든 널 값을 제거하는 것이다. 코틀린에서 예제 2-1처럼 변수 타입에 뒤따라오는 물음표 없이 변수를 정의하면 코틀린 컴파일러는 해당 변수에 널이 아닌 값을 요구한다.
널이 아닌 문자열을 할당
널을 할당하면 컴파일되지 않음
name 변수를 String 타입으로 선언했다는 것은 name 변수에 널을 할당할 수 없거나 name 변수 값이 널일 경우 코드가 컴파일되지 않음을 의미한다. 변수에 널을 할당 가능하게 만들려면 Ex 2-2 처럼 타입 정의에 물음표를 추가하자.
JK 롤링은 중간 이름이 없다. 롤링은 할머니 캐서린을 기리기 위해 할머니의 이니셜 K를 선택했다.
중간 이름이 없는 것보다 훨씬 심각한 문제를 겪게 될 킴 카사디안과 카니예 웨스트 부부의 아기 노스웨스트 또한 중간 이름이 없다.
ex 2-2의 Person 클래스에서 보듯이, 널 값일지라도 중간 이름이 middle 파라미터에 값을 제공해야 한다.
널 허용 변수를 식에서 사용하려고 시도하면 흥미로운 결과를 볼 수 있다. 코틀린은 개발자가 변수에 널이 아닌 값을 할당했는지를 검사하도록 요구하지만 이 작업이 생각처럼 쉽지 않다.
p.middle이 복합식(complex expression)이므로 String 타입으로 영리한 타입 변환이 불가능하다.
널이 아님을 확실(꼭 필요한 경우가 아니면 사용하지 말것)
p는 val 대신 var를 사용하기 때문에 변수 p가 정의된 시점과 p의 middle 속성에 접근하는 시점 중간에 값이 변경되었을 수도 있다고 가정하고, 영리한 타입 변환을 수행하지 않는다. 영리한 타입 변환이 수행되도록 우회하는 한 가지 방법은 널 아님 단언 연산자라 부르는 거듭 느낌표(!!)를 사용하는 것이다. 널 아님 단언 연산자 !!가 하나라도 있다면 이는 코드 스멜이다. !! 연산자는 변수가 널이 아닌 값으로 다뤄지도록 강제하고 해당 변수가 널이라면 예외를 던진다. 널 값에 !! 연산자를 사용하는 것은 코틀린에서 NullPointerException을 만날 수 있는 몇 가지 상황 중 하나이므로, 가능하면 사용하지 않도록 노력하자.
이런 상황에서는 안전 호출 연산자(?.)를 사용하는 것이 좋다. 안전 호출은 쇼트 서킷 평가 방식으 예제 2-5처럼 값이 널이면 null을 돌려준다.
안전 호출. 결과 타입은 Int?이다.
문제는 결과 추론 타입도 널 허용 타입이라는 점이다. 따라서 middleNameLength의 타입은 아마 사용하고자 했던 타입이 아니라 Int? 타입이므로 ex 2-6처럼 안전 호출 연산자와 엘비스 연산자(?:)를 병행해서 사용하는 것이 유용하다.
middle이 널일 경우 엘비스 연산는 0을 리턴한다.
엘비스 연산자는 자신의 왼쪽에 위치한 식의 값을 확인해서 해당 값이 널이 아니면 그 값을 리턴한다. 만약 엘비스 연산자 왼쪽 값이 널이면 엘비스 연산자는 자신의 오른쪽에 위치한 값을 돌려준다. ex 2-6에서는 정수 또는 널일 수 있는 p.middle?.length의 값을 확인해서 값이 정수면 해당 정수 값을 리턴하고, 널이면 해당 식은 0을 리턴한다.
엘비스 연산자의 오른쪽은 식이므로 함수의 인자를 확인할 때 return이나 throw를 사용할 수 있다.
끝으로 코틀린은 안전 타입 변환 연산자를 제공한다. 안전 타입 변환 연산자의 목적은 타입 변환이 올바르게 동작하지 않는 경우 ClassCastException이 발생하는 상황을 방지하는 것이다. 예를 들어 어떤 인스턴스를 Person 타입으로 변환을 시도했지만 해당 인스턴스가 널일 수도 있는 상황이라면 ex 2-7처럼 코드를 작성할 수 있다.
변수 p1의 타입은 Person? 이다.
타입 변환은 성공하여 그 결과 Person 타입이 되든가, 실패하여 그 결과 p1이 널 값을 받는다.
2.2 자바에서 널 허용성 지시자 추가하기
이슈: 코틀린 코드가 자바 코드와 상호 작용이 필요하고 널 허용성 어노테이션을 강제하고 싶다.
해법: 코틀린 코드에 JSR-305 널 허용성 어노테이션을 강제하려면 컴파일 타임 파라미터 Xjsr305=strict를 사용한다.
설명: 코틀린의 주요 기능 중 하나는 컴파일 시간에 타입 시스템에 널 허용성을 강제하는 것이다. String 타입으로 변수를 정의하면 해당 변수는 절대 널이 될 수 없다. 반면에 String? 타입으로 정의하면 예제 2-8처럼 해당 변수는 널이 될 수 있다.
널이 될 수 없거나 컴파일되지 않는다.
타입에 있는 물음표는 널 허용 타입을 나타낸다.
이 코드는 널 허용성 메커니즘이 없는 자바 코드와 상호작용하기 전까지는 잘 동작한다. 자바는 javax.annotation 패키지에 @Nonnull 어노테이션이 정의되어 있지만 이 사양은 개발이 중단된 상태다. 하지만 많은 라이브러리가 JSR-305 호환 어노테이션을 사용 중이며 코틀린은 해당 호환 라이브러리를 지원한다. 예를 들면 스프링 프레임워크를 사용할 때 예제 2-9처럼 그레이들 빌드 파일에 다음 예제의 코드를 추가함으로써 호환성을 강제할 수 있다.
Last updated
Was this helpful?