I have a mixed project, Java
and Kotlin
classes, and I want to know how I can refer to companion objects
from my Java
classes.

- 14,544
- 8
- 57
- 81
3 Answers
A companion object in Kotlin has static backing fields and methods in order to interop with Java, so you can essentially treat them like a static class, if you have annotated them correctly (using @JvmStatic and @JvmField). So:
class C {
companion object {
@JvmStatic fun foo() {}
fun bar() {}
}
}
foo can be accessed from Java like a static function. Bar cannot.
C.foo(); // works fine
C.bar(); // error: not a static method
C.Companion.foo(); // instance method remains
C.Companion.bar(); // the only way it works
You can do the same with fields, except you use JvmField
class Key(val value: Int) {
companion object {
@JvmField val COMPARATOR: Comparator<Key> = compareBy<Key> { it.value }
}
}
Then:
// Java
Key.COMPARATOR.compare(key1, key2);
// public static final field in Key class
You can also use const.
// file: Example.kt
object Obj {
const val CONST = 1
}
class C {
companion object {
const val VERSION = 9
}
}
const val MAX = 239
In Java:
int c = Obj.CONST;
int d = ExampleKt.MAX;
int v = C.VERSION;
For the nitty-gritty details, see Java to Kotlin interop in the documentation (examples are all copy-pasted from there anyway).
I recommend getting to know (and using) the JvmStatic and JvmField annotation well, if you want to interop with Java often, since they're really crucial to smooth Kotlin to Java interaction.

- 4,163
- 3
- 28
- 47
-
This is a bit misleading, you do not need to use the annotations at all, unless you want to convert from companion instance to a static reference. You should clarify that you can access companion object directly and then you have the OPTION to use the annotations for further control. – Jayson Minard May 25 '17 at 22:12
-
The examples show the different ways to access the from Java (including non-annotated ways), so I don't see how this is misleading at all. And as I note - if you want to work with it like a static class in Java (which will usually be the case if you're working with a pre-existing code base), you need to annotate (or have only const/lateinit). The alternative is going through all your Java code to insert .Companion. and .Companion.get... which is a fine way to make the transition from Java to Kotlin as cumbersome as possible. – Michael A. May 25 '17 at 23:18
-
It is the opening sentence, the wording makes it sound like it can only interoperate if you use the annotations. Even though later samples show other cases, the opener (as I read it) seems to say only one path is available. Others might read it differently, but maybe it could open up a little more clearly. – Jayson Minard May 26 '17 at 13:22
-
For the last code is should be `int d = CKt.MAX` , are I'm right? – murt Oct 26 '17 at 10:58
-
No. It's assuming a file example.kt, within which the const MAX is defined. Fixed the example so this is clearer. – Michael A. Nov 03 '17 at 22:17
Okay! If you have something like:
class MyKotlinClass {
companion object {
val VAR_ONE = 1
val VAR_TWO = 2
val VAR_THREE = 3
fun printOne() {
println(VAR_ONE)
}
}
}
you could access the fields from your Java class in this way
public class MyJavaClass {
private void myMethod(){
MyKotlinClass.Companion.getVAR_ONE();
//The same for methods
MyKotlinClass.Companion.printOne();
}
}
This is the Kotlin class with companion object.
class A {
companion object {
@JvmStatic fun foo() {}
fun bar() {}
}
}
Calling Kotlin class of companion object from Java:
A.foo();
A.Companion.foo();
A.Companion.bar();

- 8,890
- 6
- 44
- 59