Static Methods in Kotlin: A Complete Guide for Java Developers

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Static Methods in Kotlin: How a Java Developer Can Navigate the World of object and companion

\n\n

If you write in Java and are just starting to learn Kotlin, you've probably asked yourself: "Where is static here?". In Java, we are used to writing public static void main() or MathUtils.max() — it's convenient, simple, and doesn't require creating an object. But in Kotlin, the keyword static does not exist. At all. Completely.

\n\n

Don't panic. Kotlin developers haven't gone crazy — they simply decided that static methods can be implemented more elegantly, without global state and with a clearer architecture. In this article, we'll cover all the ways to replace Java static in Kotlin: from simple package-level functions to the powerful companion object. You'll learn when to use what and see live code examples.

\n\n

Let's go! 🚀

\n\n
\n\n

Why is there no static in Kotlin? (and that's a good thing)

\n\n

In Java, static is essentially a global variable or method tied to the class, not to an instance. It's convenient for utilities, but violates OOP principles: static members cannot be overridden, are difficult to test, and create tight couplings.

\n\n

Kotlin encourages a cleaner approach: functions and properties can exist at the package level (without a class at all!) or be organized into object singletons. And if you need to bind a method to a class (like in Java), use companion object. Let's break down each option.

\n\n
\n\n

Method 1: Package-Level Functions (Simplest)

\n\n

In Kotlin, you can declare a function or property simply in a file, outside a class. This is an analog of a static method in Java, but without the unnecessary wrapper of a utility class.

\n\n

Example:

\n\n
// File: MathUtils.kt\npackage com.example.utils\n\nfun max(a: Int, b: Int): Int {\n    return if (a > b) a else b\n}\n\nval PI = 3.14159 // package-level constant
\n\n

Now this function can be called from anywhere (after import):

\n\n
import com.example.utils.max\nimport com.example.utils.PI\n\nfun main() {\n    println(max(10, 20)) // 20\n    println(PI)          // 3.14159\n}
\n\n

When to use: for simple utility functions and constants that don't require grouping into a class. This is the easiest way to get "static" behavior.

\n\n
\n\n

Method 2: Object Singleton (for a Group of Related Functions)

\n\n

If you need to group several static methods together (like MathUtils in Java), use an object. This is a singleton — a single instance that is created automatically on first access.

\n\n

Example:

\n\n
object StringUtils {\n    fun isEmpty(str: String?): Boolean {\n        return str.isNullOrEmpty()\n    }\n\n    fun capitalizeFirst(str: String): String {\n        return str.replaceFirstChar { it.uppercase() }\n    }\n\n    const val EMPTY_STRING = ""\n}
\n\n

Usage:

\n\n
fun main() {\n    println(StringUtils.isEmpty(null))   // true\n    println(StringUtils.capitalizeFirst("kotlin")) // Kotlin\n    println(StringUtils.EMPTY_STRING)    // ""\n}
\n\n

Important: object is a full-fledged class. It can implement interfaces, have initializers, and even inherit from other classes. But it cannot have constructors (except private).

\n\n
\n\n

Method 3: Companion Object (for Methods Related to a Class)

\n\n

This is the closest analog to Java static inside a class. companion object is a companion object that lives inside the class. Its methods and properties are called via the class name, like static ones.

\n\n

Example:

\n\n
class User(val name: String, val age: Int) {\n    companion                

Blogs

Book Recommendations