When is the constructor keyword required in a Kotlin primary constructor, and what does a private primary constructor enable?
answer
- constructor keyword: only for modifiers or annotations
- private constructor → force factory creation
- Companion object can call private constructor
- private ctor ≠ singleton (use object)
- Visibility: public/internal/protected/private
basics
~10 sUsually you skip the constructor keyword. You must write it when you add a visibility modifier like private, or an annotation. A private primary constructor stops outside code from calling it directly.
solid answer
~30 sThe `constructor` keyword in the class header is optional and almost always omitted. It is **required** when the primary constructor has a **visibility modifier** (`private`, `internal`, `protected`) or one or more **annotations** (e.g. `@Inject`, `@JvmOverloads`). A `private constructor` is a common idiom to force construction through factory functions or companion-object methods — useful for validation, caching, or enforcing invariants — and underpins the controlled-instantiation pattern. Note: making the primary constructor private does not by itself make the class a singleton; for singletons use `object`. Visibility on the constructor controls who may invoke it, independent of the class's own visibility.
code
kotlin · 10 linesclass UserId private constructor(val raw: Long) {
companion object {
fun from(raw: Long): UserId {
require(raw > 0) { "id must be positive" }
return UserId(raw)
}
}
}
// UserId(5) // error: constructor is private
UserId.from(5) // ok, validatedgo deeper
Knows the constructor keyword is usually omitted.
States the two cases requiring the keyword and the factory-via-private-constructor idiom.
Explains companion-object access, smart constructors for invariants, and validation/normalization use cases.
Designs construction policy for a library: factories vs constructors, ABI/visibility surface, and invariant enforcement strategy.
## The optional keyword Most classes never write `constructor`: ```kotlin class Point(val x: Int, val y: Int) ``` The keyword becomes **mandatory** in exactly two situations: ### 1. A visibility modifier on the constructor ```kotlin class Token private constructor(val value: String) class Cache internal constructor(val size: Int) ``` Visibility options: `public` (default), `internal` (same module), `protected` (open/abstract class subtypes), `private` (declaring class/file scope). ### 2. An annotation on the constructor ```kotlin class Service @Inject constructor(val repo: Repo) class Widget @JvmOverloads constructor(val w: Int = 0, val h: Int = 0) ``` ## Why use a private primary constructor A private constructor blocks direct `MyType(...)` calls from outside, channeling creation through **factory functions** — typically in the **companion object**: ```kotlin class Email private constructor(val value: String) { companion object { fun of(raw: String): Email { require("@" in raw) { "invalid email" } return Email(raw.trim().lowercase()) } } } ``` Benefits: - **Validation / normalization** before an instance exists. - **Caching / interning** (return a cached instance). - **Returning subtypes** from the factory. - Enforcing that all instances satisfy an invariant (a "smart constructor"). ## Misconceptions - Private constructor ≠ singleton. For a single instance use `object Foo`. - The companion object (declared inside the class) can still call the private constructor — private here means *within the class*, and the companion is a member. - Constructor visibility is separate from class visibility: a `public` class may have a `private` constructor. ## Interaction with sealed classes Many sealed-class hierarchies effectively have non-public constructors so subclasses are the only creators — though sealed restriction is its own mechanism.
- Can the companion object call a private primary constructor?Yes. The companion object is a member of the class, so it has access to the private constructor — that is exactly how the factory pattern works.
- Does a private primary constructor make the class a singleton?No. It only restricts who can construct it. Use an `object` declaration for a true singleton.
saying these in an interview costs you the question
- Saying the constructor keyword is always required
- Claiming a private constructor creates a singleton
- Thinking the companion object can't access the private constructor
- Confusing class visibility with constructor visibility
- Forgetting annotations also force the constructor keyword