What is a use-site target on a Kotlin annotation (e.g. @get:, @field:, @param:), and why is it needed when annotating a property?
answer
- One property = field + getter + setter + ctor param
- Prefix before the colon: @get:/@field:/@param:
- Wrong target = annotation silently ignored
- Targets: get/set/field/param/property/receiver/delegate
basics
~20 sOne Kotlin property can become several Java pieces: a field, a getter, a setter, a constructor parameter. A use-site target like @get: or @field: tells the compiler which of those pieces the annotation should land on.
solid answer
~40 sA property declaration in Kotlin generates multiple JVM elements: a backing field, a getter, optionally a setter, and (for primary-constructor properties) a constructor parameter. An annotation written on the property is ambiguous about which element it targets, so Kotlin lets you disambiguate with a use-site target prefix: `@get:`, `@set:`, `@field:`, `@param:`, `@property:`, `@receiver:`, and `@delegate:`. For example `@field:JsonProperty("id")` puts the annotation on the Java field, while `@get:JsonProperty("id")` puts it on the getter. This matters because libraries that use reflection (Jackson, JPA, validation) inspect a specific element; targeting the wrong one means the annotation is silently ignored. If you omit the target, Kotlin applies a default resolution order based on the annotation's `@Target`.
code
kotlin · 5 linesclass Account(
@field:Id val id: Long, // annotation on the field
@get:JsonProperty("user_name") val name: String, // on the getter
@param:Positive val balance: Long, // on the ctor parameter
)go deeper
Knows a property maps to multiple JVM elements and that @get:/@field:/@param: choose one.
Can predict which library reads which element and fix a silently-ignored annotation.
Explains the default resolution order and the full target set including @property:/@delegate:.
Frames it as a Kotlin-to-JVM impedance issue and sets team conventions for interop annotations.
## The problem use-site targets solve In Kotlin, a single line like `val id: Long` is more than a field. When compiled to JVM bytecode, a property can produce **several distinct elements**: - a **backing field** (the actual storage slot) - a **getter** method - a **setter** method (only for `var`) - a **constructor parameter** (only when the property is declared in the primary constructor) If you write `@SomeAnnotation val id: Long`, the compiler must decide which of these the annotation belongs to. A **use-site target** is a prefix before the colon that removes the ambiguity. ## The available targets ```kotlin class User( @param:NotBlank val name: String, // the constructor parameter @field:Id val id: Long, // the backing field @get:JsonProperty("email") val email: String, // the getter ) ``` The full set: - `@get:` — the property getter - `@set:` — the property setter (only valid on `var`) - `@field:` — the backing field - `@param:` — the primary-constructor parameter - `@property:` — the Kotlin property itself (a Kotlin-only target, stored in metadata) - `@receiver:` — the receiver parameter of an extension function/property - `@delegate:` — the field that stores a delegate instance (`by`) ## Why it matters in practice Many Java libraries read annotations **reflectively** off a *specific* element. Jackson and JPA often look at fields **or** getters; Bean Validation may look at the field, the getter, or the constructor parameter depending on configuration. If your annotation lands on the wrong element, it is simply ignored — no error, just silently wrong behavior. That makes the wrong-target bug hard to spot. ## Default behavior If you don't specify a target, Kotlin doesn't pick randomly — it follows a fixed **default resolution order** based on which targets the annotation declares in its `@Target`. (Covered in depth in a separate question.)
- What happens if you put an annotation on a property without any use-site target?Kotlin applies the default resolution order: it picks the first applicable target from the list param, property, field (skipping ones not allowed by the annotation's @Target).
- Why might a Jackson @JsonProperty annotation appear to do nothing?It probably landed on the wrong element. If Jackson reads getters but the annotation defaulted onto the field (or vice versa), it is ignored. Adding @get: or @field: fixes it.
Like addressing a letter to one specific person in a shared household — without the name, the mail goes to whoever the default rule says.
saying these in an interview costs you the question
- Thinking a Kotlin property is just a field
- Claiming the target prefix is optional cosmetic syntax with no effect
- Saying a wrong target causes a compile error (it usually doesn't)
- Confusing use-site targets with the annotation's own @Target meta-annotation