Hanbit the Developer
Kotlin Documentation | Annotations 본문
Category: Concepts
문서 링크: https://kotlinlang.org/docs/annotations.html
어노테이션은 메타 데이터를 코드에 붙일 수 있는 수단이다. 어노테이션을 정의하기 위해 annotation 구분자를 클래스 앞에 붙인다.
annotation class Fancy
Additional attributes of the annotation:
- @Target: 어떤 유형에 어노테이션이 붙을 수 있는지를 명시한다.(클래스, 함수, 프로퍼티, 표현식)
- @Retention: 주석이 컴파일된 클래스 파일에 저장되는지 여부, 런타임에 리플랙션을 통해 표시되어야 하는지 여부를 결정한다.(기본적으로 양쪽 모두 참임)
- @Repeatable: 하나의 원소에 같은 어노테이션이 여러 번 붙을 수 있게 허용한다.
- @MustBeDocumented: 어노테이션이 공개 API의 일부이며 생성된 API 문서에 표시된 클래스나 메서드에 포함되어야 한다고 지정한다.
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy
Usage
@Fancy class Foo {
@Fancy fun baz(@Fancy foo: Int): Int {
return (@Fancy 1)
}
}
class Foo @Inject constructor(dependency: MyDependency) { ... }
class Foo {
var x: MyDependency? = null
@Inject set
}
Constructors
annotation class Special(**val why: String**)
@Special(**"example"**) class Foo {}
인자 타입:
- Primitive types(Int, Long etc.)
- Strings
- Classes(Foo::class, 인자 선언은 KClass로 한다. 예시: val arg: KClass<*>)
- Enums
- Other annotations: 인자로 쓰일 땔 앞에 @가 붙지 않음
- 위 타입들을 감싸고 있는 Arrays
*non-nullable
Instantiation
어노테이션은 인터페이스의 형태를 하기 때문에 인스턴스를 생성할 수 있다.
annotation class InfoMarker(val info: String)
fun processInfo(marker: InfoMarker): Unit = TODO()
fun main(args: Array<String>) {
if (args.isNotEmpty())
processInfo(getAnnotationReflective(args))
else
processInfo(InfoMarker("default"))
}
Lambdas
람다에 붙어서 invoke() 메소드에 적용될 수 있다.
annotation class Suspendable
val f = @Suspendable { Fiber.sleep(10) }
Annotation use-site targets
Annotation이 생성되는 정확한 방법을 명시하려면 다음과 같이 타겟을 명시해야 한다:
@Target(
AnnotationTarget.FIELD,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.PROPERTY_GETTER
)
annotation class Ann
class Example(
@Ann val hbk: String, // without target
@field:Ann val foo: String, // annotate Java field
@get:Ann val bar: String, // annotate Java getter
@param:Ann val quux: String // annotate Java constructor parameter
)
위 코틀린 코드를 Java로 디컴파일한 내용은 다음과 같다:
public final class Example {
@NotNull
private final String hbk;
@Ann
@NotNull
private final String foo;
@NotNull
private final String bar;
@NotNull
private final String quux;
@NotNull
public final String getHbk() {
return this.hbk;
}
@NotNull
public final String getFoo() {
return this.foo;
}
@Ann
@NotNull
public final String getBar() {
return this.bar;
}
@NotNull
public final String getQuux() {
return this.quux;
}
public Example(@Ann @NotNull String hbk, @NotNull String foo, @NotNull String bar, @Ann @NotNull String quux) {
Intrinsics.checkNotNullParameter(hbk, "hbk");
Intrinsics.checkNotNullParameter(foo, "foo");
Intrinsics.checkNotNullParameter(bar, "bar");
Intrinsics.checkNotNullParameter(quux, "quux");
super();
this.hbk = hbk;
this.foo = foo;
this.bar = bar;
this.quux = quux;
}
}
*@Ann이 어디에 부착되었는지 확인할 것. 타겟을 명시하지 않은 것이 FIELD로 지정된 이유는, Ann의 타겟 정의 부분에서 첫번째 아이템이 AnnotationTarget.FIELD이기 때문이다.
@file:JvmName("Foo")
package org.jetbrains.demo
같은 타겟의 여러 어노테이션이 있는 경우 다음과 같이 표기할 수 있다.
class Example {
@set:[Inject VisibleForTesting]
var collaborator: Collaborator
}
타겟 리스트는 다음과 같다.
- file
- property
- field
- get
- set
- receiver(receiver parameter of an extension function or property)
- fun @receiver:Fancy String.myExtension() { ... }
- param(constructor parameter)
- setparam(property setter parameter)
- delegate(the field storing the delegate instance for a delegated property)
타겟을 명시하지 않는 경우, 사용 중인 어노테이션의 @Target 어노테이션에 따라 대상이 결정된다. 만약 @Target에 여러 타겟이 명시되어 있을 경우 다음 리스트에서 첫번째로 적용 가능한 타겟이 사용된다:
- param
- property
- field
Java annotations
named argument syntax:
// Java
public @interface Ann {
int intValue();
String stringValue();
}
// Kotlin
@Ann(intValue = 1, stringValue = "abc") class C
value 인자라는 특별한 경우에서는 이름을 명시하지 않아도 된다.
// Java
public @interface AnnWithValue {
String value();
}
// Kotlin
@AnnWithValue("abc") class C
Arrays as annotation parameters
value가 배열인 경우, 코틀린에서 vararg로 변환된다.
// Java
public @interface AnnWithArrayValue {
String[] value();
}
// Kotlin
@AnnWithArrayValue("abc", "foo", "bar") class C
일반적인 경우:
// Java
public @interface AnnWithArrayMethod {
String[] names();
}
@AnnWithArrayMethod(names = ["abc", "foo", "bar"])
class C
Accessing properties of an annotation instance
// Java
public @interface Ann {
int value();
}
// Kotlin
fun foo(ann: Ann) {
val i = ann.value
}
Repeatable annotations
'Kotlin' 카테고리의 다른 글
Kotlin Documentation | Reflection (0) | 2023.05.22 |
---|---|
Kotlin Documentation | Destructuring declarations (1) | 2023.05.22 |
Kotlin Documentation | Asynchronous programming techniques (0) | 2023.05.22 |
Kotlin Documentation | Equality (0) | 2023.05.22 |
Kotlin Documentation | Null safety (0) | 2023.05.22 |