지금까지 함수와 클래스에 대한 많은 feature를 보았지만, 이들은 전부 클래스나 함수의 이름을 명확하게 명시할 것을 요구한다. 예를 들어 함수를 호출하려면 해당 함수가 정의된 클래스나 이름, 또는 파라미터 타입을 알아야 한다. 그러나 Annotations
과 reflection
를 사용하면 이러한 제약에서 벗어나 미리 알고있지 않은 임의의 클래스를 다룰 수 있게 해준다.
애노테이션의 핵심 컨셉은 코틀린에서도 비슷하다. 애노테이션은 추가적인 메타데이터를 선언할 때 사용할 수 있게 해준다. 메타데이터는 소스코드나 컴파일된 클래스 파일, 또는 런타임 때 접근가능하다.
애노테이션을 적용하기 위해서는 선언 시 함수나 클래스 이름 앞에 @ 캐릭터를 넣으면 된다.
import org.junit.*
class MyTest {
@Test fun testTrue() { //애노테이션 적용
Assert.assertTrue(true)
}
}
애노테이션은 다음과 같은 파라미터를 가질 수 있다: 원시 타입의 값, 문자열, enum, 클래스 참조, 다른 애노테이션 클래스, 그리고 지금까지 말한 요소들로 이뤄진 배열이 있다.
애노테이션 인자를 지정하는 문법은 자바와 약간 다르다.
애노테이션 인자는 컴파일 시점에 인지 가능해야 한다. 따라서 임의의 프로퍼티를 인자로 지정할 수는 없다. 프로퍼티를 애노테이션 인자로 사용하려면 그 앞에 const 변경자를 붙여야 한다.
const val TEST_TIMEOUT = 100L
@Test(timeout = TEST_TIMEOUT) fun testMethod() { ... }
만약 일반적인 프로퍼티를 사용하고 애노테이션 인자로 사용한다면, ““Only ‘const val’ can be used in constant expressions.”에러를 얻게 된다.
일반적으로, 코틀린에서 하나의 선언은 자바에서 여러 개의 선언과 상응한다. 따라서 이들 중 어떤 요소가 애노테이션이 되어야 하는지 알기 어렵다.
애노테이트 되어야 하는 특정한 요소는 use-site target 선언으로 명시할 수 있다. 이 선언은 @ 캐릭터와 애노테이션 이름 사이에 위치하며, :으로 분리되어 보인다. 다음 그림에서는 get이 use-site target이 된다.