코틀린과 자바의 몇가지 차이점 맛보기

최인준·2024년 5월 23일
0
post-thumbnail

서론

이번에 코틀린을 공부하게 되었다.

코틀린을 공부하면서 몇가지 흥미로웠던 점을 기록용, 홍보용(?)으로 남기고자 포스팅을 작성하게 되었다!

이 글을 보고 코틀린에 흥미를 느껴 공부나 프로젝트 도입을 고려해보는 사람들이 많아지길 바랍니다!😀

자바와의 차이점을 위주로 다루려고 한다. 단순한 문법적인 차이가 아니라 언어의 특성에 대한 차이를 다룬다.

문(statement)과 식(expression)의 구분

62 페이지

자바에서 ‘문’으로 다루던 것들이 코틀린에선 ‘식’인 경우가 있다.

(’문’은 값을 만들어내지 못하고 ‘식’은 결과를 만들어낸다.)

대표적으로 if문에 대해서만 보겠다.

먼저 예시 코드를 살펴보자!

fun isPositive(num: Int): Boolean {
    if(num > 0) return true
    else return false
}

간단히 정수를 인자로 받아 양수인지 판별해주는 함수이다.

자바에서도 해당함수를 구현하기 위해선 동일하게 구현한다. 하지만 코틀린에서 if문을 다르게 대하기 때문에 코드를 더 간결히 할 수 있다.

자바에서는 if문이 하나의 문장이기 때문에 return 값으로 if문 자체가 들어갈 수 없다.

하지만 코틀린에서는 if문이 하나의 결과를 만들어내는 ‘식’으로 취급되기 때문에 다음과 같이 구현할 수 있다.

fun isPositive(num: Int): Boolean {
    return if(num > 0) true
    else false
}

각 조건마다 return 문을 쓰지 않고 맨 앞에 return문 하나만 두어 간결히 표현할 수 있다.

여기서 코틀린 함수의 특징을 활용해 더욱 간결하게 만들 수 있다.

fun isPositive(num: Int) = if(num > 0) true else false

*이 특징에 대해선 다음 글을 참조

10화 코틀린(Kotlin) 함수(function)

디폴트 접근자 구현 제공

자바에서 getter, setter를 구현해야할 때를 생각해보자.

접근자 메소드를 직접 구현해주거나 Lombok을 활용하여 구현해야 한다.

Lombok을 활용하면 어노테이션을 통해 간단히 구현할 수 있는 것은 맞지만 어쨋든 부가적인 코드가 필요한 것은 사실이다.

코틀린에서는 기본적으로 이러한 접근자 메소드를 제공한다.

Rectangle이라는 클래스를 예시로 어떻게 제공하는지 보자!

class Rectangle(
		val height: Int, // val : 불변
        var width: Int   // var : 가변
)

이와 같이 생성자를 정의하면 자동으로 getter, setter를 제공해준다!

생성자를 정의했을 뿐인데 접근자 메소드가 알아서 만들어진 것이다.

위와 같이 val로 불변으로 선언된 프로퍼티는 getter만 제공이 되고, var로 선언된 프로퍼티는 setter까지 제공된다.

생성자에 정의된 필드가 아닌 다른 필드에 대해 getter가 필요한 상황이 있을 수도 있다.

예를 들어 해당 객체가 정사각형인 지 여부에 대한 필드가 하나 있다고 해보자.

그렇다면 다음과 같이 커스텀 접근자를 직접 정의해줄 수 있다.

class Rectangle(
        val height: Int,
        var width: Int
){
    val isSquare: Boolean
        get(){
            return height == width
        }
}

위와 같이 정의하고 다음과 같이 실행해볼 수 있다.

>>> val rectangle = Rectangle(10, 10)
>>> println(rectangle.isSquare)
true

스마트 캐스트

자바에서 instanceOf와 같이 코틀린에서는 is를 활용해 동일한 검사를 할 수 있다.

예를들어 다음과 같은 함수가 있다고 해보자.

fun eval(e: Expr) {
    if(e is Num) {
        val n = e as Num // type cast 
        return n.value
    }
}

(Expr과 Num이 무엇이고 어떤 객체인 지는 일단 생각하지 말자)

구현된 코드를 보면 Expr이라는 타입의 객체를 받아서 해당 객체가 Expr의 하위클래스 중 하나인 Num 객체인지 검증하고 있다. 그리고 Num 객체가 맞다면 Num객체로 type cast를 진행한다.

자바에서는 이와 같이 구현 해야한다. 하지만 코틀린에서는 타입 캐스팅 과정이 불필요한 과정이다.

코틀린에서는 한번 is로 검사하고 난 후라면 컴파일러가 캐스팅을 수행해준다.

즉, 위에서 주석이 쓰여진 캐스팅 하는 과정은 생략해도 된다. (생략하자)

예외 구분 X

Exception에 대해서 자바에서 약간 불편했던 점이 코틀린에서는 개발자 입장에서 더 편리하게 해주는 부분이있다.

우선 자바와 코틀린의 가장 큰 차이는 코틀린은 throws절이 없다.

이게 무슨 말인지는 다음 코드를 보며 이해해보자.

fun readNumber(reader: BufferedReader): Int? {
	try{
		val line = reader.readLine()
		return Integer.parseInt(line)
	}
	catch (e: NumberFormatException) {
		return null
	}
	finally{
		reader.close()
	}
}

자바에서는 IOException이 체크 예외이기 때문에 throws절이 함수 선언뒤에 필요하다.

어떤 함수가 던질 가능성이 있는 예외나 그 함수가 호출한 다른 함수에서 발생할 수 있는 예뢰를 모두 catch로 처리해야 하며, 처리하지 않은 예외는 throws절에 명시해야 한다.

코틀린은 체크 예외와 언체크 예외를 구별하지 않는다.

이게 왜 편리한 지 생각해보자.

  • reader.close()는 IOException을 던질 수 있다.
  • 하지만 이 구문대로 닫다가 실패하는 경우 클라이언트 프로그램이 취할 수 있는 의미 있는 동작이 딱히 없다.
  • 그러므로 IOException을 잡아내는 코드는 그냥 불필요하다.

그렇기에 불필요하게 IOException을 catch하거나 throws 하는 코드가 코틀린에서는 필요없다.

결론

코틀린과 자바의 차이는 더 많지만 간단히 추려보았다.

코틀린은 자바와의 100% 상호운용성을 목표로 하면서 자바의 불편한 점들을 많이 커버해내기 위한 목적으로 나온 언어이기 때문에 코틀린을 사용하면 코드가 훨씬 간결해지기도 하며 불편함이 해소되기도 한다.

또한 이 포스팅에서는 자바와의 차이에 중점을 두었기 때문에 소개하지 않은 것들이 많은데 코틀린은 특히 null에 대한 많은 안정성을 제공한다.

자바를 사용하면서 NPE를 자주 만났더라면 코틀린을 사용하면서 그럴 일이 없을 것이다.(거의..)

당장 위의 사례들만을 보더라도 코드가 훨씬 짧아지고 리소스가 줄어들 것을 알 수 있다.

자바에 익숙하신 분들이라면 코틀린을 도입하면서 더 큰 생산성을 경험해볼 수 있을 것 같다!

1개의 댓글

comment-user-thumbnail
2024년 6월 7일

코틀린도 NPE를 많이 접하게 되더라구요,,, 좋은 글 잘 보고 갑니다 ^^!

답글 달기