skip to content

What is the default visibility of a top-level declaration in Kotlin, and how does that compare to Java?

level: juniorimportance: must knowfreq 60%

answer

  1. Kotlin default = public
  2. Java default = package-private
  3. Kotlin has NO package-private
  4. Four modifiers: public/internal/protected/private
  5. internal ~ closest to package-private but module-wide

basics

~10 s

By default everything in Kotlin is public — visible everywhere. In Java, members with no modifier are package-private (visible only in the same package). Kotlin has no package-private at all.

solid answer

~30 s

Kotlin's default visibility is `public`: a top-level function, class, or property with no modifier is visible from any module that depends on the file. This contrasts with Java, where omitting a modifier gives **package-private** (default) access, visible only within the same package. Kotlin deliberately drops package-private; its four modifiers are `public`, `internal`, `protected`, and `private`. For top-level declarations only `public`, `internal`, and `private` apply (`protected` is for class members). So the Java habit of relying on "no modifier = package scope" doesn't translate — you must use `internal` (module scope) or `private` (file scope) to restrict a top-level declaration.

go deeper

for a junior

States that the default is public and that Java's default differs (package-private).

for a middle

Lists all four modifiers and notes Kotlin removed package-private, with internal as the rough analog.

for a senior

Explains the module boundary of internal vs Java's package boundary and the API-surface implications of a public default.

for a principal

Discusses library API governance: explicit-API mode, binary compatibility, and why a public default pushes responsibility onto authors to seal internals.

## Default is public In Kotlin, if you write no visibility modifier, the declaration is **`public`** — accessible from anywhere it can be imported, including other modules. This applies to top-level functions, classes, objects, and properties as well as class members. ```kotlin fun greet() = "hi" // public by default class Service // public by default val VERSION = "1.0" // public by default ``` ## Java contrast Java has **four** access levels: `public`, `protected`, *default (package-private)*, and `private`. The **default** (no keyword) is package-private: visible only inside the same package. Kotlin's default is the opposite end of the spectrum — `public`. ## No package-private in Kotlin Kotlin **removed package-private entirely**. Packages in Kotlin are organizational namespaces, not an access-control boundary. The four Kotlin modifiers are: - `public` (default) — everywhere - `internal` — same **module** (compilation unit) - `protected` — declaring class + subclasses (class members only) - `private` — top-level: same **file**; member: same class `internal` is Kotlin's nearest replacement for Java's package-private, but its boundary is a **module**, not a package, and it's coarser/broader. ## Why this matters in practice A Java developer porting code may expect "no modifier = hidden from other packages." In Kotlin the same declaration is fully public API. To hide it you must explicitly add `internal` or `private`. ```kotlin internal fun helper() {} // visible only inside this module private fun secret() {} // visible only inside this file ``` ## Library design note Because the default is `public`, library authors must be deliberate about what they expose — every unmarked declaration is part of the public API surface and subject to binary/source compatibility concerns.

  • What's the closest Kotlin equivalent to Java's package-private, and why isn't it exact?
    `internal` — but it scopes to the whole module, not a single package, so it's broader. There's no per-package access control in Kotlin.
  • Why might a public-by-default language be risky for library authors?
    Every unmarked declaration is exposed API; you can accidentally publish implementation details and then owe backward compatibility on them. Authors must mark internals explicitly.

Java's no-keyword is a 'staff only' door (your package); Kotlin's no-keyword is a wide-open front door (public).

saying these in an interview costs you the question

  • Saying the default is package-private (that's Java)
  • Claiming Kotlin has a package-private level
  • Thinking the default is `internal`
  • Confusing module scope with package scope for `internal`
  • Assuming Java access habits transfer unchanged

context