Kotlin, @Jvm으로 Java에서 사용하기

JiCheol Choo
Nov 6 · 6 min read

JvmStatic

The @JvmStatic annotation tells the Kotlin compiler to generate a static version of the annotated member or method.

  • object로 생성(싱글톤)된 코틀린 파일을 자바에서 사용할 경우, 코틀린의 변수 또는 함수를 가져다 쓰기 위해선 kotlinFileName.INSTANCE.valueName or funName으로 사용해야 한다. 이 부분을 좀 더 편하게, 자바처럼 사용하기 위해서 @JvmStatic Annotation을 사용할 수 있다.
  • 예를 들어, 첫 번째처럼 사용 시, @JvmStatic을 사용하지 않는다면, Repository.INSTANCE.getNextGuestId()이렇게 호출이 될 것이다. 하지만, 두 번째처럼 사용한다면 Repository.getNextGuestId()으로 사용 가능하다.
val nextGuestId
get() = _nextGuestId++
@JvmStatic
val nextGuestId
get() = _nextGuestId++

JvmName

The @JvmName annotation is a powerful tool that influences how Kotlin names classes, properties, and methods in the bytecode it generates for the Java Virtual Machine (JVM). We’ll discuss another of its uses later in this codelab.

  • 코틀린 파일 명 자체를 가져다 쓸 때 JvmName 선언을 통해 가져다 쓰면 파일명만 가져다 쓸 수 있어 편하다.
  • 예를 들어, StringUtils라는 파일을 만들고 내부를 kotlin-extension으로 만들어 놓고, 자바에서 사용 시 StringUtilsKt.extenstionFunName 이 아닌, StringUtils.extensionFunName이 가능하다. 즉, 더 추가적으로 작업할 필요없이 자바처럼 가져다 쓸 수 있게 만들어 주는 어노테이션이다.
@file:JvmName("StringUtils")
  • 아래 처럼, 변수에 JvmName을 사용함으로써 getValueName으로 변수를 가져오지 않고 선언한 valueName으로 가져올 수 있다. (“get:” 은 생략 가능)
@get:JvmName("hasSystemAccess")
val hasSystemAccess
get() = "sys" in groups
  • 또한, 아래처럼 set: 을 명시함으로써 setter의 역할을 대신할 수 있다.
class Color {
@set:JvmName("updateRed")
var red = 0f
@set:JvmName("updateGreen")
var green = 0f
@set:JvmName("updateBlue")
var blue = 0f
}
// Java에서 사용 방법
Color color = new Color();
color.updateRed(1.5f);
System.out.println("red = "+color.getRed());

JvmOverloads

  • 자바에서는 코틀린처럼 기본 값을 제공하지 않으므로, 코틀린 데이터 클래스 파일을 가져다 쓰기 위해선 primary constructor와 JvmOverloads를 사용해야 한다.
data class User(...)    data class User @JvmOverloads constructor(...)

JvmField

  • 클래스 내에 있는 속성 값을 가져오기 위해 직접 필드 접근을 사용한다. 코틀린에서, 속성들은 보통 게터와 세터를 통해 노출되어진다. 이건 val 속성을 포함한다. @JvmField 어노테이션을 사용함으로써 이 행동 변화를 가능하게 한다. 이게 클래스 내 속성에 적용될 때, 코틀린은 게터(그리고 var속성에 대한 세터) 메소드들을 생성하는걸 건너 뛸 수 있을 거고, 백업 필드에 직접적으로 액세스 할 수 있다.

‘const’ might be used instead of ‘@JvmField’

  • In Kotlin, the only types that can be const are primitives, such as int, float, and String. In this case, because BACKUP_PATH is a string, we can get better performance by using const val rather than a val annotated with @JvmField, while retaining the ability to access the value as a field.
  • 코틀린에서, const를 할 수 있는 타입은 오직 int, float, String. ~~~ @JvmField와 함께 사용한 val 어노테이트 보다 const val 를 사용함으로써 더 좋은 퍼포먼스를 가질 수 있다. ~~

Throw

  • 자바는 “checked exception”의 개념을 가지고 있고, 이는 유저가 파일 이름을 잘못 입력하는 것과 같이, 개발자의 실수가 없기 때문에 코드에서 발생할 수 문제들이다. “checked exception(확인된 예외)”가 발견된 후에, 개발자는 그때 그 문제를 수정하는 방법에 대해 유저에게 피드백을 제공할 수 있다.

반면에, 코틀린은 “checked exception”을 가지고 있지 않아 이런 문제가 발생하고, 해결 방법으로 IOEception을 추가한다.

@JvmStatic   
@Throws(IOException::class)
fun saveAs(path: String?) {
val outputFile = File(path)
if (!outputFile.canWrite()) {
throw FileNotFoundException("Could not write to file: $path")
}
// Write data...
}

위의 내용을 정리하자면,

@JvmStatic to generate static members and methods.

@JvmOverloads to generate overloaded methods for functions that have default values.

@JvmName to change the name of getters and setters.

@JvmField to expose a property directly as a field, rather than via getters and setters.

@Throws to declare checked exceptions.

이렇게 됩니다. 자바와 혼합하여 사용 시 참고하면 좋을 것 같네요.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

참고 싸이트

    JiCheol Choo

    Written by

    “기본부터”라는 말을 좋아하지만 정작 기본이 없는… 기본을 쌓아나가려고 합니다. 안드로이드 개발자로 성장하기 위해 열심히 책상앞에 앉아 두들겨보겠습니다.

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade