How do array-typed annotation parameters work in Kotlin, including vararg and the array literal syntax? How do they differ from Java's interop expectations?
answer
- One-dimensional arrays only; no nested arrays
- [..] literal valid only inside annotations; else arrayOf
- vararg val names: String -> array in bytecode (String[])
- Only one vararg; Java uses {..} brace syntax
- Array/vararg defaults must be const, e.g. = []
basics
~10 sAnnotations can take arrays. You declare Array<String> and pass values with [..] or arrayOf(...). A vararg parameter lets callers pass items without wrapping them, and it shows up as an array to Java.
solid answer
~40 sAnnotation parameters may be arrays of allowed element types (`Array<String>`, `IntArray`, `Array<KClass<*>>`, etc.). You supply them with the **array literal** `[a, b]` (allowed only inside annotation arguments) or with `arrayOf(...)`/`intArrayOf(...)`. A parameter may also be `vararg`, e.g. `annotation class Roles(vararg val names: String)`, so callers write `@Roles("admin", "user")` without an explicit array. In bytecode a `vararg` annotation parameter is just an array (Java sees `String[]`), and Java callers pass `{"admin", "user"}`. Only **one** `vararg` is permitted and it follows normal vararg rules. Element types must themselves be allowed annotation types; arrays are **one-dimensional** — you cannot have `Array<Array<String>>`. Defaults work too: `vararg val names: String = []` or `val tags: Array<String> = ["default"]`. Reading reflectively from Kotlin yields an `Array`/primitive array.
code
kotlin · 9 linesimport kotlin.reflect.KClass
annotation class Imports(vararg val modules: KClass<*>)
annotation class Headers(val names: Array<String> = [])
@Imports(String::class, Int::class)
@Headers(names = ["X-Trace", "X-Auth"])
class Config
// Java sees: Class<?>[] modules and String[] namesgo deeper
Knows annotations can take arrays and that [..] or arrayOf supplies them.
Uses vararg for ergonomic multi-value parameters and knows arrays are one-dimensional only.
Explains the vararg -> array bytecode mapping, Java brace interop, the annotation-only [..] literal, and constant-array defaults.
Weighs vararg vs explicit Array in the public API for Kotlin/Java consumers and processor ergonomics, knowing all become arrays.
## Array-typed parameters An annotation parameter can be a **one-dimensional array** of any allowed element type: - `Array<String>`, `Array<KClass<*>>`, `Array<Level>` (enum), `Array<Inner>` (annotation). - Specialized primitive arrays: `IntArray`, `LongArray`, `BooleanArray`, etc. - **No nesting**: `Array<Array<String>>` is illegal. ### Supplying array values Two syntaxes: ```kotlin annotation class Tags(val values: Array<String>) @Tags(values = ["a", "b"]) // array-literal form, only valid inside annotations @Tags(values = arrayOf("a", "b")) // factory form also works class A ``` The `[...]` **array literal** is special syntax permitted *only* in annotation arguments (historically `arrayOf` was required; the literal was added for ergonomics). For primitive arrays use the matching factory, e.g. `intArrayOf(1, 2)`. ## `vararg` annotation parameters You can mark exactly one parameter `vararg`: ```kotlin annotation class Roles(vararg val names: String) @Roles("admin", "user") // no array wrapper needed class Admin ``` - Only **one** `vararg` per annotation, following standard vararg rules. - In bytecode the `vararg` becomes an **array** parameter (`String[]`), so it is just an array annotation member to the JVM. - You may still pass an array explicitly using the spread operator `*`: `@Roles(*roleArray)` where `roleArray` is a `const`/literal array — but the values still must be compile-time constants. ## Java interop - A Kotlin array (or vararg) annotation member appears to Java as `String[]` (or `Class[]`, `int[]`, etc.). - Java callers use brace syntax: `@Roles({"admin", "user"})` or `@Tags({"a", "b"})`. - A Kotlin `Array<KClass<*>>` member surfaces as `Class<?>[]` in Java. ## Defaults Arrays and varargs can have constant defaults: ```kotlin annotation class Tags(val values: Array<String> = []) // empty default annotation class Roles(vararg val names: String = arrayOf("guest")) ``` The default value, like every annotation value, must be a compile-time constant array. ## Reading back ```kotlin val t = A::class.annotations.filterIsInstance<Tags>().first() val arr: Array<String> = t.values // Kotlin reflection returns an Array ``` ## Pitfalls - Trying to use `List` instead of `Array` — not allowed. - Nesting arrays — illegal. - Forgetting the `[...]` literal is annotation-only; outside annotations use `arrayOf`. - Declaring two `vararg`s or a `vararg` not last — compile error.
- Can an annotation have two vararg parameters?No. Like any function, at most one vararg is allowed, and standard vararg positioning rules apply.
- How does a Java caller pass values to a Kotlin vararg annotation parameter?Using brace syntax, e.g. @Roles({"admin", "user"}), because it compiles to a String[] member.
vararg is like a 'list as many as you want' field on a form; under the hood the clerk staples them into one attachment (an array).
saying these in an interview costs you the question
- Using List instead of Array for a multi-valued annotation parameter
- Trying to declare a nested array like Array<Array<String>>
- Using the [..] literal outside an annotation
- Thinking vararg becomes something other than an array in bytecode
- Declaring more than one vararg parameter