Kotlin 문법 배우기
코틀린의 변수와 타입 다루기
1. 변수 선언 키워드
코틀린에서 변수 선언 키워드로 var
과 val
이 있다.
var number1 = 10
val number2 = 10
두 키워드의 차이점으로는 var
은 수정할 수 있는 변수, val
은 수정 불가능한 변수를 의미한다. 단, val
키워드로 선언한 컬렉션의 element는 추가/제거 가능하다.
실무 팁: 모든 변수는 일단 val
키워드로 생성하고 꼭 필요한 경우에만 var
로 변경하자.
2. 코틀린의 타입
1) Primitive Type
자바 코드에서 다음과 같은 코드가 있다고 해보자.
long number1 = 10L;
Long number2 = 1_000L;
자바에서는 long
은 primitive type, Long
은 reference type으로 두 타입은 다르게 구분된다. 따라서 자바에서는 두 타입끼리 연산을 할 때 boxing, unboxing이 일어나면서 불필요한 객체 생성이 발생한다는 문제가 있다.
하지만 코틀린에서는 long
타입의 변수를 다음과 같이 선언한다.
val number1: Long = 10L
val number2: Long = 1_000L
코틀린에서느 모두 Long
이렇게 선언해주고 있다. 코틀린에서는 숫자, 문자, 불리언과 같은 몇몇 타입들은 실행 시에 primitive type으로 표현되지만, 실제 코드에서는 평범한 클래스처럼 보인다.
즉 두 타입 모두 Long
으로 표현되지만 연산을 하게 될 경우 내부적으로 primitive type으로 바꿔서 연산해준다는 것이다.
2) nullable 변수
코틀린에서는 자바와 다르게 null이 들어갈 수 있다.
라는 의미를 다르게 간주한다. 왜냐하면 코틀린에서는 기본적으로 모든 변수에 null이 들어갈 수 없게끔 만들어놓았기 때문이다.
변수에 null이 들어갈 수 있다.
라는 의미를 주고 싶다면 다음과 같이 표현한다.
val number3: Long? = 1L
number3 = null
바로 타입 뒤에 ?
를 붙여 표현한다.
참고로 자바의 @NotNull
이 선언된 자바의 변수값을 코틀린으로 변환할 때는 nullable 타입 변수로 받지 않는다.
3) 객체의 인스턴스화
자바에서는 객체를 인스턴스화할 때 new
연산자를 사용해줬지만, 코틀린에서는 new
를 붙이지 않는다.
new
를 붙이지 않고 다음과 같이 인스턴스화한다.
val person = Person("아무개")
3. 코틀린의 null 체크
앞의 nullable 변수에서 설명한 것 처럼 코틀린에서는 null이 가능한 타입을 다르게 취급한다. 예제로 알아보기 위해 다음과 같은 자바 코드를 코틀린으로 변환해보겠다.
public boolean isEmptyString(String str) {
if (str == null) {
throw new IllegalArgumentException("str이 null입니다.");
}
return str.isEmpty();
}
public Boolean isContainsA(String str) {
if (str == null) {
return null;
}
return str.contains("A");
}
public boolean isEqualsA(String str) {
if (str == null) {
return false;
}
return str.equals("A");
}
위 함수들을 코틀린으로 변환하기 전에 먼저 Safe Call과 Elvis 연산자에 대해 알아보자.
1) Safe Call
Safe Call은 null이 아니면 실행하고, null이면 그대로 null이 되는 연산자이다. 다음과 같이 ?.
이런 형태로 표현한다.
val str: String? = "Hello"
str.length // 불가능, String? 타입으로 null이 들어올 수 있는 타입이기 때문이다.
str?.length // 가능, Safe Call, null이 아니면 length 실행, null 이면 이 값 그대로 null이 됨
2) Elvis 연산자
Elvis 연산자는 앞의 연산 결과가 null 이라면 뒤의 값을 사용해라. 라는 의미의 연산자이다. 다음과 같이 ?:
형태로 표현한다.
val str: String? = "Hello"
str?.length ?: 0 // str?.length 연산의 결과가 null이라면 0을 사용하라
그럼 위 Safe Call과 Elvis 연산자를 사용해서 아까 자바 코드 함수들을 변환해보자.
fun isEmptyString(str: String?): Boolean {
return str?.isEmpty() ?: throw IllegalArgumentException("str이 null입니다.")
}
fun isContainsA(str: String?): Boolean? {
return str?.contains("A")
}
fun isEqualsA(str: String?): Boolean {
return str?.equals("A") ?: false
}
또한 다음과 같이 early return 구문도 간단하게 작성할 수 있다.
if (number == null) {
return 0;
}
// 다음 로직
👇
number ?: return 0
// 다음 로직
3) null 아님 단언
코틀린에서 nullable 타입이지만 비즈니스 로직 상 아무리 해도 null이 될 수 없는 변수에, null 아님 단언을 통해 단언 신호를 해줄 수 있다. 이 단언은 !!.
으로 표현하며, 다음과 같이 사용할 수 있다.
fun isContainsA(str: String?): Boolean {
return str!!.contains("A") // str은 null이 들어올 수 있는 타입이지만 !!. 단언으로 실행 가능함
}
만약 null 아님 단언을 했지만 null이 들어온다면, 그 떄는 NPE가 발생하게 된다.