skip to content

What is the default visibility of a Kotlin class, function, or property when you write no modifier, and how does this differ from Java?

level: juniorimportance: must knowfreq 75%

answer

  1. No modifier = public in Kotlin
  2. Java no modifier = package-private
  3. Kotlin dropped package-private entirely
  4. internal replaces package-private
  5. Writing 'public' is redundant

basics

~10 s

In Kotlin, anything without a modifier is public, meaning visible everywhere. In Java, a member with no modifier is package-private, visible only within the same package.

solid answer

~40 s

Kotlin's four visibility modifiers are public, private, protected, and internal. The default (no keyword) is public for top-level declarations and class members, so you rarely write public explicitly. This is the opposite of Java, where omitting a modifier gives package-private (default-access) visibility, restricted to the same package. Kotlin deliberately has no package-private concept; the nearest equivalent is internal, which is module-scoped rather than package-scoped. So a Kotlin class member declared with no modifier is callable from anywhere the class itself is visible, whereas the same Java member would be hidden outside its package. Idiomatic Kotlin omits public and uses private or internal explicitly to narrow scope.

go deeper

for a junior

States that the default is public and that this differs from Java.

for a middle

Knows Kotlin has no package-private and that internal is the closest equivalent.

for a senior

Explains the design rationale and migration implications when porting Java code.

for a principal

Discusses how default-public shapes API design and the value of explicit internal/private for evolvable library surfaces.

## What 'default visibility' means Visibility (or access) modifiers control *where* a declaration can be referenced. Kotlin has exactly four: `public`, `private`, `protected`, and `internal`. When you write **no** modifier, the declaration is **`public`** — visible to any code that can see its containing scope. ```kotlin class Service { // public class val name = "x" // public property fun run() {} // public function } fun helper() {} // public top-level function ``` Because `public` is the default, writing it explicitly is redundant and most style guides (and the Kotlin compiler's lint) discourage it. ## How this differs from Java | | No modifier means… | Scope | |---|---|---| | **Kotlin** | `public` | Everywhere the declaration is reachable | | **Java** | package-private ("default" access) | Only the **same package** | Java has four levels: `public`, `protected`, *default* (package-private), `private`. Kotlin intentionally **dropped package-private** — there is no keyword for "visible within this package only." Packages in Kotlin are purely an organizational/namespacing tool, not a visibility boundary. ## The Kotlin replacement for package-private Kotlin offers **`internal`** instead: visible within the same **module** (a set of files compiled together — a Gradle source set, a Maven module, an IntelliJ module). This is broader than a package but narrower than fully public, and it's the idiomatic way to hide library internals from external consumers. ## Practical consequences - A Kotlin member with no modifier is part of your **public API**. If you don't want that, you must explicitly write `private` or `internal`. - Migrating Java code: a package-private Java member has **no exact Kotlin equivalent**; you usually map it to `internal` or `private`. ## Recall - Kotlin no-modifier ⇒ `public`. - Java no-modifier ⇒ package-private. - Kotlin has **no** package-private; use `internal`.

  • Why did Kotlin remove package-private?
    Package-private leaks across packages too easily (anyone can declare a class in your package) and packages are weak boundaries; module-scoped internal is a stronger, more meaningful unit for hiding internals.
  • Is writing 'public' an error?
    No, it compiles fine, but it's redundant and flagged by the compiler/IDE as a 'redundant visibility modifier'.

Kotlin assumes the door is open by default; Java assumes it's open only to your immediate neighbors (the package).

saying these in an interview costs you the question

  • Saying the default is private
  • Claiming Kotlin has package-private
  • Thinking no-modifier in Kotlin matches Java's no-modifier
  • Believing 'public' must be written explicitly
  • Confusing internal with package scope

context