skip to content

How does an annotation class differ from a normal class in Kotlin in terms of body, instantiation, and visibility?

level: middleimportance: must knowfreq 45%

answer

  1. no body vs full body
  2. compiler instantiates at @Name vs you call Name()
  3. public by default vs chosen visibility
  4. only annotations work after @
  5. annotations can't extend classes

basics

~10 s

An annotation class has no body, you don't create it with new/constructor calls in your code, and it's public by default. A normal class has a body, is instantiated, and you choose its visibility.

solid answer

~40 s

An `annotation class` is a constrained class form. It has **no body** (no methods, no init blocks, no nested behavior beyond allowed members), it is **implicitly public**, and you never instantiate it directly with a constructor call — the compiler builds the instance when you write `@Name(...)`. A normal `class` can hold state, define functions, have init logic, choose any visibility (private/internal/public), and is created via `Name()`. The `annotation` modifier also unlocks the `@` application syntax: only annotation classes can be used after `@`. Conversely, an annotation class cannot do many things a normal class does — it cannot have a non-primary-constructor body of functions, cannot extend another class, and its members are restricted. This makes it a pure metadata carrier rather than a behavioral type.

go deeper

for a junior

Recalls that annotations have no body and you don't instantiate them like normal classes.

for a middle

Lists the concrete differences: bodiless, compiler-instantiated, public, no inheritance, restricted members.

for a senior

Explains why the language imposes these restrictions — pure metadata carrier — and how the @ gate works.

for a principal

Reasons about the design tradeoffs of metadata-only types and how that shape supports tooling/reflection stability.

## The contrast at a glance | Aspect | `annotation class` | normal `class` | |---|---|---| | Body `{ }` | omitted / empty by design | usual body with functions, init | | Instantiation | done by compiler at `@Name(...)` site | `Name()` in your code | | Visibility | implicitly **public** | you choose (public/internal/private) | | Usable after `@` | yes | no | | Inheritance | cannot extend a class | can extend / implement | | Members | restricted (no arbitrary functions) | any members | ## No body An annotation is declared bodiless: ```kotlin annotation class Marker ``` You do **not** add functions or `init { }` blocks. Its purpose is to be metadata, not behavior. (Constructor **parameters** for annotation values exist, but that is a separate sibling topic; here the point is the *shape* has no behavioral body.) ## You don't `new` it You never write `val m = Marker()` to use it. Instead you apply it: ```kotlin @Marker class Service ``` The compiler synthesizes the annotation instance and stores it as metadata. (Reflectively, frameworks can obtain an instance, but that's reading, not your construction.) ## Implicitly public You never need (and shouldn't add) `public`: ```kotlin annotation class Marker // public // public annotation class Marker // redundant ``` A normal class lets you restrict visibility (`internal class Helper`); an annotation is public so it can be referenced wherever applied. ## The @ gate The `@Name` syntax is reserved for annotation classes. Try to write `@SomePlainClass` and it won't compile. The `annotation` modifier is what flips a type into this metadata role. ## Why the restrictions Because annotations exist only to be **attached and later read**, the language strips away class features that would imply behavior or state-at-runtime. This keeps them a predictable, serializable-into-class-metadata shape.

  • Can an annotation class extend another class or implement an interface?
    No. Annotation classes cannot have a supertype list; they are a closed, metadata-only shape.
  • If annotations have no body, how do they hold data like @Column(name = "id")?
    Through primary-constructor parameters (a sibling topic). The point here is they have no behavioral body of functions/init.

saying these in an interview costs you the question

  • Saying you instantiate an annotation with a constructor in normal code to apply it
  • Claiming annotation classes can have init blocks or member functions
  • Believing annotations can extend a base class or implement interfaces
  • Adding redundant `public` and thinking it is required
  • Thinking a normal class can be used after @ with no annotation modifier

context