노트/Java to Kotlin

변수, 타입, 연산자

작성

Java 코드를 Kotlin 으로 옮기며 단계(step)마다 .java 와 .kt 를 나란히 두고 비교한 기록이다. 이 노트는 step 01(변수), 04(연산자), 05(제어문)에서 적은 것이다.

변수

fun main() {
    val num1 = 10L          // val num1: Long = 10L 과 같다. 타입을 추론한다.
    val num2 = 10L
    var num3: Long? = 1_000L   // null 이 들어갈 수 있으면 타입 뒤에 ? 를 붙인다.

    val num4 = num1 + num2  // + num3 은 타입 불일치로 컴파일이 안 된다.

    num3 = 2_000_000L
    num3 = null

    val person = Person("junha")   // new 를 쓰지 않는다.
    println(person.name)
}
  • 타입을 적지 않아도 추론한다.
  • val 은 Java 의 final 처럼 다시 대입할 수 없고, var 는 대입할 수 있다.
  • 기본적으로 모든 변수에 null 을 넣을 수 없게 설계되어 있다. nullable 이면 Long? 처럼 명시한다. nullable 타입은 아예 다른 타입으로 취급되어서 Long 과 더할 수 없다.
  • 원시 타입(primitive)과 참조 타입을 구분하지 않는다. 모든 타입을 객체로 다루고, 연산할 때는 알아서 long 으로 바꿔 계산한다. 오토박싱과 언박싱을 Kotlin 이 처리한다.
  • 객체를 만들 때 new 를 쓰지 않는다.
  • 문자열은 Java 와 같이 큰따옴표를 쓴다.
  • 파일 이름과 클래스 이름이 같을 필요가 없다. 한 파일에 클래스와 함수를 여러 개 둘 수 있다.
  • 같은 패키지 안에 있으면 import 하지 않아도 된다.

보일러플레이트가 사라진다

class Person(var name: String)

Java 에서 필드, 생성자, getter, setter 를 적던 클래스가 한 줄이 된다. getter 와 setter 는 자동으로 만들어진다.

바이트코드로 확인하기

IntelliJ 에서 Tools → Kotlin → Show Kotlin Bytecode → Decompile 을 누르면 Kotlin 코드가 어떤 Java 코드로 바뀌는지 볼 수 있다. 위 한 줄짜리 Person 이 getter 와 setter 를 가진 Java 클래스로 풀리는 것을 눈으로 확인할 수 있다.

연산자

val money1 = JavaMoney(1_000L)
val money2 = JavaMoney(2_000L)

if (money1 < money2) {
    println("money1 < money2")
}
  • Java 와 달리 객체를 비교 연산자로 비교하면 자동으로 compareTo() 를 호출한다.
  • 동등성(equality)은 두 객체의 값이 같은지 묻는 것이고 == 를 쓴다. 동일성(identity)은 두 객체가 같은 객체인지, 즉 주소가 같은지 묻는 것이고 === 를 쓴다.

제어문

fun validateScoreIsNotNegative(score: Int) {
    if (score < 0) {
        throw IllegalArgumentException("${score} cannot be smaller than 0")
    }
}

fun getPassOrFail(score: Int): String {
    return if (score > 50) {
        "P"
    } else {
        "F"
    }
}
  • if-else 가 값이 되는 expression 이라 바로 return 할 수 있다.
  • 문자열 안에 ${score} 로 값을 끼워 넣는다.
  • 예외는 new 없이 throw IllegalArgumentException(...) 으로 던진다.