How does @Target restrict where an annotation can be applied, and what happens if you apply it to a disallowed element? Name several AnnotationTarget values.
answer
- @Target = whitelist of AnnotationTarget values
- Wrong target → compile error
- Property, field, getter, setter are separate targets
- EXPRESSION needs SOURCE retention
- FILE target for @file:...
basics
~10 s@Target lists the kinds of code elements (class, function, property, parameter, etc.) the annotation is allowed on. If you put it somewhere not in that list, the code won't compile.
solid answer
~40 s@Target takes one or more AnnotationTarget enum constants and the compiler enforces them: applying the annotation to any element outside the listed set is a compile-time error. Common values include CLASS, FUNCTION, PROPERTY, FIELD, VALUE_PARAMETER, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER, LOCAL_VARIABLE, TYPE, TYPE_PARAMETER, EXPRESSION, FILE, and ANNOTATION_CLASS. Note that a Kotlin property and its backing field, getter, and setter are distinct targets — annotating a property doesn't automatically annotate the field, which is where use-site targets (@field:, @get:) come in. If you omit @Target, Kotlin defaults to a broad set of declaration targets (but not EXPRESSION/TYPE). EXPRESSION and similar require SOURCE retention since they don't survive into bytecode.
code
kotlin · 8 lines@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER)
@Retention(AnnotationRetention.RUNTIME)
annotation class Cacheable
class Repo {
@Cacheable fun load() {}
@get:Cacheable val cached: Int = 0 // getter target via use-site
}go deeper
Knows @Target is a list of allowed places and wrong placement won't compile.
Names many AnnotationTarget values and understands property/field/getter/setter are separate targets needing use-site targets.
Explains the @Target ↔ use-site-target interaction and the EXPRESSION/SOURCE constraint precisely.
Designs annotation target sets deliberately to constrain misuse and align with framework processing expectations.
## What @Target does `@Target(vararg allowedTargets: AnnotationTarget)` declares the precise set of code positions where your annotation is legal. The compiler checks every usage; a usage on an element not in the set fails to compile with *"This annotation is not applicable to target '...'"*. ## AnnotationTarget values you should know - **CLASS** — class, interface, object, also annotation classes. - **ANNOTATION_CLASS** — only annotation classes (for meta-annotations). - **FUNCTION** — named functions and lambdas-as-declarations. - **PROPERTY** — Kotlin properties (the property concept itself). - **FIELD** — backing fields (and `@JvmField`). - **PROPERTY_GETTER / PROPERTY_SETTER** — the accessor methods. - **VALUE_PARAMETER** — function/constructor parameters and `val/var` in primary constructors. - **CONSTRUCTOR** — primary or secondary constructors. - **LOCAL_VARIABLE** — local `val/var`. - **TYPE** — type usages, e.g. `val x: @NonNull String`. - **TYPE_PARAMETER** — generic type parameters `<@Ann T>`. - **TYPE_USE-like**: covered by TYPE / TYPE_PARAMETER. - **EXPRESSION** — arbitrary expressions (requires SOURCE retention). - **FILE** — applies to the whole file (`@file:JvmName(...)`). ## Property vs field vs accessors In Kotlin a single `val name: String` declaration spawns several distinct annotatable elements: the **property**, its **backing field**, its **getter**, and (for `var`) its **setter**. An annotation targeting only `FIELD` cannot be written directly as `@Ann val name` without a **use-site target** (`@field:Ann`). So @Target interacts closely with use-site targets: ```kotlin @Target(AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) annotation class Column class Row(@field:Column val id: Int) // needs @field: because Column targets FIELD ``` ## Disallowed-target error ```kotlin @Target(AnnotationTarget.FUNCTION) annotation class OnlyFun @OnlyFun fun ok() {} // @OnlyFun class Nope // ERROR: not applicable to target 'class' ``` ## Defaults Omitting @Target makes the annotation usable on a broad default set of declarations (class, function, property, etc.) but not on expressions or type usages. To allow those you must opt in explicitly (and use SOURCE retention for EXPRESSION).
- Why might an annotation declared with @Target(FIELD) require @field: at the use site?Because a Kotlin property declaration defaults to the property/getter target; you must redirect the annotation to the backing field explicitly with @field:.
- Can you target EXPRESSION with RUNTIME retention?No — expressions aren't kept in bytecode, so EXPRESSION targets require SOURCE retention.
saying these in an interview costs you the question
- Thinking annotating a property automatically annotates its field
- Believing a wrong target is a runtime error instead of compile-time
- Not knowing property/field/getter/setter are distinct targets
- Claiming EXPRESSION works with RUNTIME retention