Kotlin DISCUSSION

What replaces Java static methods and constants in Kotlin: companion object, object or top-level?

Started by sony Kotlin companion objectstatic methodsconst valJvmStatictop-level functions
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

What replaces Java static methods and constants in Kotlin: companion object, object or top-level?

sony Kotlin Forum
#1

I am converting a Java utility class to Kotlin. It has public static final int MAX_CHANNELS = 8, a couple of static helper methods and a static factory method. Kotlin has no static keyword, and the automatic converter put everything into a companion object.

What are the options, how do they differ at the bytecode level, and what does Java code calling this class need to write afterwards?

Community replies 4

Re: What replaces Java static methods and constants in Kotlin: companion object, object or top-level?

#2

There are three places to put such things. Top-level declarations in a file, outside any class, are the closest match for stateless helpers and constants: fun crc8(data: ByteArray): Int at file level needs no class at all and is called as crc8(bytes). An object declaration is a singleton, useful when the helpers share state. A companion object inside a class is a singleton tied to that class, whose members are called with the class name, Frame.parse(bytes); this is the natural home for factory methods that need access to a private constructor.

Re: What replaces Java static methods and constants in Kotlin: companion object, object or top-level?

#3

For constants use const val MAX_CHANNELS = 8, either at top level or inside an object or companion. const is allowed only for primitive types and String with a value known at compile time; the compiler inlines the value at every use, and from Java it is an ordinary static final field. A plain val in a companion is not a static field for callers: it is accessed through a getter on the companion instance.

One consequence of inlining: if a library changes a const val, code compiled against the old value keeps the old number until it is recompiled.

Re: What replaces Java static methods and constants in Kotlin: companion object, object or top-level?

#4

What Java sees depends on annotations. A top-level function in Crc.kt compiles to a static method of a class named CrcKt, so Java calls CrcKt.crc8(bytes); put @file:JvmName("Crc") at the top of the file to choose a nicer class name. A companion member without annotations is an instance method of the companion, so Java must write Frame.Companion.parse(bytes).

Add @JvmStatic to the function and the compiler also generates a true static method, giving Frame.parse(bytes). For a non-const property, @JvmField exposes it as a static field.

Re: What replaces Java static methods and constants in Kotlin: companion object, object or top-level?

#5

It helps to remember that a companion is a real object, not syntax for statics. It exists at runtime as one instance, it can implement an interface, it can be passed around as a value, and it can have extension functions defined on it. That is more capable than Java statics, but it also means a companion full of unrelated helpers carries a little indirection for no benefit.

A reasonable layout for your class: constants as top-level or companion const val, pure helpers as top-level functions in the same file (marked private if only that file uses them), and the factory in the companion with @JvmStatic if Java callers exist.

TEP COMMUNITY