How do you apply @JvmOverloads to a primary constructor, and why is this a common pattern for Android custom Views?
answer
- Write 'constructor' keyword to annotate primary ctor
- @JvmOverloads goes before constructor
- Generates the View constructor ladder
- Inflation needs (Context, AttributeSet)
- Replaces hand-written this(...) chaining
basics
~10 sPut @JvmOverloads on the primary constructor, after the visibility/constructor keyword: class MyView @JvmOverloads constructor(...). It generates the multiple constructors Android's layout-inflation and Java code expect, so you don't hand-write three or four constructors.
solid answer
~30 sOn a primary constructor you must write the constructor keyword explicitly and place the annotation before it: class MyView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr). The compiler then emits the (Context), (Context, AttributeSet), and (Context, AttributeSet, Int) constructors that the Android View framework and XML inflation rely on (inflation reflectively looks for the (Context, AttributeSet) constructor). This replaces the verbose Java pattern of writing several constructors that chain via this(...). The same right-to-left default-dropping rule applies. Note for Views you typically still want defStyleAttr handling, and @JvmOverloads cleanly produces the standard ladder.
code
kotlin · 6 linesclass BadgeView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr)
// JVM constructors: (Context), (Context,AttributeSet), (Context,AttributeSet,int)go deeper
Knows the annotation can go on constructors and helps Android Views.
Writes the correct primary-constructor syntax and enumerates the generated constructors.
Explains the reflection-based inflation requirement and why the constructor ladder must physically exist.
Connects it to framework integration contracts generally and reasons about reflection/runtime failure modes.
## Syntax on a primary constructor A primary constructor normally omits the `constructor` keyword. To annotate it you must add the keyword back and place the annotation in front: ```kotlin class MyView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, ) : View(context, attrs, defStyleAttr) { // ... } ``` If the constructor were `private`/`internal`, the visibility goes after the annotation: `@JvmOverloads private constructor(...)` — but a private constructor exposed to Java this way rarely makes sense. ## What gets generated Two parameters have defaults, so **N+1 = 3** constructors become visible: - `MyView(Context)` - `MyView(Context, AttributeSet)` - `MyView(Context, AttributeSet, int)` The shorter ones forward to the full one with the default values, dropping defaults right-to-left. ## Why Android Views care Android's **XML layout inflation** uses reflection to find a `(Context, AttributeSet)` constructor; programmatic creation uses `(Context)`; theming/styling uses `(Context, AttributeSet, int)`. In Java you'd hand-write all three and chain them with `this(...)`. With Kotlin + defaults + @JvmOverloads you write **one** primary constructor and get the standard ladder for free, matching what the framework expects. ## Caveats - The framework actually invokes these via reflection, so the constructors must truly exist on the JVM — which is exactly what @JvmOverloads guarantees. Without it, only the maximal-arity constructor would exist and inflation could fail. - Default-dropping is still right-to-left; the ordering `(context, attrs, defStyleAttr)` matches the framework's expected reduction order, which is why this pattern works so cleanly. - Beyond Android, the same approach helps any Java/reflection-based framework (e.g., serialization, DI) that expects specific constructor arities.
- Why must you write the 'constructor' keyword in the primary constructor here?Because annotations (and modifiers) on a primary constructor require the explicit constructor keyword; without an annotation it can be omitted.
- What breaks if you omit @JvmOverloads on a custom View's Kotlin constructor?Only the maximal-arity constructor exists on the JVM, so XML inflation looking for (Context, AttributeSet) can fail at runtime with no-such-constructor errors.
saying these in an interview costs you the question
- Forgetting the explicit constructor keyword is required
- Placing the annotation in the wrong position relative to constructor/visibility
- Thinking inflation can use Kotlin defaults without generated constructors
- Claiming @JvmOverloads only works on functions, not constructors