How can I make reference to companion objects from Java?
Asked Answered
L

3

7

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.

Loraineloralee answered 25/5, 2017 at 20:16 Comment(0)
N
9

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.

Netty answered 25/5, 2017 at 20:36 Comment(5)
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.Evermore
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.Netty
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.Evermore
For the last code is should be int d = CKt.MAX , are I'm right?Nacre
No. It's assuming a file example.kt, within which the const MAX is defined. Fixed the example so this is clearer.Netty
N
3

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();
    }
}
Nonetheless answered 25/5, 2017 at 20:17 Comment(0)
A
0

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();
Adsorbent answered 25/5, 2017 at 20:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.