애너테이션은 커스텀 메타데이터를 정의하고 이 메타데이터를 소스코드상의 선언, 식, 전체 파일 등의 요소에 엮는 방법을 제공한다.
본 포스팅에서는 코틀린을 자바와 비교하며 코틀린 애너테이션의 사용 방법과 특징을 설명하고자 한다.
1. 메타 애너테이션
메타 애너테이션은 애너테이션을 정의할 때 사용하는 애너테이션으로서, 새롭게 정의하고자 하는 애너테이션에 대한 정보를 담고 있다. 코틀린과 자바에서 모두 존재하는 애너테이션도 있고, 그렇지 않은 애너테이션도 있다.
물론 공통으로 사용한다 하더라도 패키지는 엄연히 다르며(코틀린: kotlin.annotation / 자바: java.lang.annotation), 해당 애너테이션의 파라미터로 사용되는 상수(코틀린: AnnotationTarget / 자바: ElementType)에도 차이가 있으니 둘의 차이점을 잘 알고 사용해야 한다.
1) 자바-코틀린에 모두 존재
- @Target: 애너테이션이 적용 가능한 대상을 지정한다
- @Retention: 애너테이션이 유지되는 범위를 지정한다
- @Repeatable: 동일한 애너테이션이 하나의 요소에 중복으로 적용될 수 있게 한다
2) 자바만
- @Inheried: 애너테이션이 자손 클래스에 상속되도록 한다
- @Documented: 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다
3) 코틀린만
- @MustBeDocumented
- 애너테이션이 공개 API의 일부인 경우 이 애너테이션을 붙여서 문서에 꼭 포함시킬 것을 명시한다
- 해당 애너테이션은 자바의 @Document와 같은 역할을 하며 코틀린 표준 문서화 엔진인 Dokka에 의해 지원된다
2. 코틀린에서 애너테이션 사용하기
1) 애너테이션 정의 (vs 자바)
// Java
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Fancy {
String value() default "hi";
}
// Kotlin
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy(
val value: String = "hi"
)
- 자바 애너테이션은 인터페이스인 반면, 코틀린 애너테이션은 전용 클래스(annotation class)로 구성된다
- 자바 애너테이션에서는 애트리뷰트를 파라미터가 없는 메서드 형태로 지정해야 하는 반면, 코틀린에서는 생성자 파라미터가 프로퍼티 역할을 함께 담당한다
2) 코틀린 애너테이션의 특징
- 코틀린의 애너테이션 클래스는 일반 클래스와 달리 멤버나 부생성자, 초기화 코드가 없다
annotation class MyAnnotation {
val text = "???" // Error
}
- 코틀린 1.3부터는 중첩 클래스, 인터페이스, 객체(동반 객체 포함)를 애너테이션 본문에 넣을 수 있다
annotation class MyAnnotation {
companion object {
val text = "???"
}
}
- 앞서 언급했던 것처럼 코틀린 애너테이션에 커스텀 애트리뷰트를 추가하고 싶다면 생성자 파라미터를 통해야만 하며, 이때 애너테이션 파라미터는 항상 val로 선언해야 한다
annotation class MyAnnotation(val text: String)
@MyAnnotation("Some useful info") // 일반 클래스 생성자를 호출하는 것처럼 파라미터에 실제 인자를 제공해야 한다.
fun annotatedFun() { ... }
- 코틀린 애너테이션은 클래스의 일종이기는 하지만, 일반적인 클래스 생성 방식으로는 인스턴스 생성이 불가하다. 단, @ 구문을 사용하면 애너테이션 인스턴스를 생성할 수 있다.
annotation class Component(val name: String = "Core")
val ioComponent = Component("IO") // error: annotation class cannot be instantiated
3. 참고
- https://kotlinlang.org/docs/annotations.html
- 코틀린 완벽 가이드
'프로그래밍 언어 > Java + Kotlin' 카테고리의 다른 글
[Java] Collection과 Collections의 차이 (0) | 2023.03.16 |
---|---|
[Java] 생성자 총정리 (0) | 2023.01.06 |
[Java] JVM을 통해 알아보는 자바 프로그램 실행방식 (0) | 2022.12.15 |
[Kotlin] BigDecimal을 비교할 때 주의하라 (0) | 2022.11.08 |
[Kotlin] scope function - let, run, also, apply, with 차이 (0) | 2022.08.13 |