- 리믹스아이콘
- OneToMany
- kotlin
- 디자인패턴
- with jdk
- oraclejdk
- Spring
- Observer Pattern
- 무료 아이콘 폰트
- 도커
- java_to_kotlin
- java
- restcontroller
- arc browser
- 옵저버패턴
- 라즈베리파이 클러스터
- restdocs
- remix icon
- fontawesome
- Spring Cloud
- Openjdk
- 라즈베리파이
- EntityGraph
- springboot
- 폰트어썸
- Docker
- QueryDSL
- openapispec
- spring cloud contract
- 전략패턴
- Today
- Total
< Dev-Kidult />
Java to Kotlin - 1. 코틀린의 타입 시스템 본문
널가능성
코틀린을 비롯한 최신언어에서는 null에 대한 문제를 실행시점이 아닌 컴파일시점에서 미리 감지하여 발생 할 수 있는 오류를 체크하고있다.
?
기존 자바에서는 NPE를 대처하기 위해서 8버전에서 Optional이라는 wrapper 클래스를 도입한다.
그럼에도 실상 쓰기에는 불편함이 많고, 업무에서도 잘 쓰이는 모습을 보지 못한다.
코틀린에서는 “?“라는 키워드를 활용하여 널가능성에 대해 처리하고있다.
var nonNull: String = "nonNull"
var nullable: String? = "nullable"
nonNull = null // Null can not be a value of a non-null type String
nuallable = null
코틀린에서는 null을 지정해주려면 타입선언끝에 “?” 라는 키워드를 붙여줘야 한다.
null을 허용하지 않는 필드 혹은 변수에 null을 지정하려면 IDE 혹은 컴파일시에 위 같은 에러메세지를 볼 수 있으며, 실행되지 않는다.
안전한 호출 연산자 ?.
String nullable = "nullable";
if(nullable != null) {
nullable.toUpperCase();
}
var nullable: String? = "nullable"
nullable?.uppercase()
엘비스 연산자 ?:
val nonNull = nullable?: "nonNull"
자바스크립트를 사용하는 사람이라면 익숙할 엘비스 연산자이다.
들어오는 값이 null일 경우에 디폴트값을 지정할 수 있도록 하는 연산자이다.
코틀린에서는 return, throw등의 연산도 식이다. 디폴트값 대신 예외를 던지거나등의 코드도 적을 수 있다.
캐스팅 as, as?
Object obj = ...
Person person = (Person) obj
val any: Any? = ...
val person = any as? Person
자바에서는 위처럼 괄호를 이용하여 캐스팅하는데 null이거나 기타등등의 이유로 캐스팅하지 못하는 상황임에도 당연히 컴파일단계에서 잡아주지 못하고 실행단계에서 오류가 나는 경우가 종종있다.
코틀린에서는 캐스팅하는데 “as” 키워드를 쓰고 있으며, “as?“를 쓰면은 캐스팅하지 못하는 상황에는 null을 return 해준다.
널이 아님 !!
var nullable: String? = "nullable"
nullable!!.uppercase()
해당값이 어떤 함수등을 거쳐 null이 아님이 확실해도 다음에 다른 함수를 호출한다고 컴파일러는 호출된 함수 안에서 해당값을 안전하게 사용할 수 있는지 인식 할 수 없다.
그럴경우에(그래도 최대한 안쓰는쪽이 좋겠지만) “!!” 키워드를 사용하여 해당 값에 null 여부 검사를 생략 할 수 있다.
늦은 초기화
lateinit
@Value("\${aws.ses.sender}")
lateinit var sender: String
위 처럼 null이 아님이 확실한데 값을 나중에 초기화해줘야 하는 상황이 있다.
그럴때는 “lateinit” 키워드를 사용하면 된다.
당연히 null을 허용하지 않기 때문에 null이 들어가면 에러가 발생하고, 초기화전에 저 “sender”는 null이 아닌 uninitialized(초기화되지 않음) 상태로 존재한다. 그렇기에 초기화전에 해당 값에 접근하여 사용하려하면은 초기화되지 않았다는 에러가 발생하게 된다.
by lazy
val x = Int by lazy { otherValue.length }
by lazy의 경우에는 당장 초기화 될 수 없고 다른 계산식의 영향을 받거나 다른 변수가 초기화 된 이후에 알 수 있는 경우에는 이 방식을 사용 할 수 있다.
위에서 x의 경우는 선언될 때 초기화 되지 않고 “처음 사용되는 순간에 초기화”가 된다.
그리고 val로 선언되어있는만큼 “처음 사용되는 순간에 초기화”된 값은 변하지 않는다.(추후에 otherValue가 변경되더라도)
원시타입
자바에서는 int, boolean, char 등등… 원시타입이 존재하지만, 코틀린에서는 기본적으로 다 null이 될 수 있어야 하므로 래퍼클래스로 감싸져있다.
Any, Any? 최상위 타입
자바에서는 Object가 클래스계층의 최상위 타입이듯, 코틀린에서는 Any타입이 모든 타입(Int등 원시타입을 포함하여)의 최상위 타입이다.
Void → Unit
자바의 void와 같은 기능을 하는 Unit이 있으며, 코틀린에서는 Unit도 하나의 타입이다.
함수에서 return값을 지정해주지 않으면 기본적으로 Unit이 지정된다.
제네릭 함수에서도 타입으로 Unit을 지정하여서 return을 안 할 수도 있다.
Nothing
코틀린에서는 반환값(return) 자체가 없는 함수가 존재 할 수도 있다.
fun fail(message: String) : Nothing {
throw IllegalStateException(message)
}
val a = b ?: fail("is null!")'개발 > Back-end' 카테고리의 다른 글
| Java to Kotlin - 3. 클래스와 함수 (0) | 2022.12.28 |
|---|---|
| Java to Kotlin - 2. 조건문과 반복문 (0) | 2022.12.28 |
| Java to kotlin - 0. kotlin? (0) | 2022.12.28 |
| Springboot - QueryBinder (0) | 2022.12.28 |
| Spring boot JPA Specification + Spring filter 파라미터로 쉽게 조회하기 (0) | 2022.04.21 |