Get companion class in companion object

Getting the class of the companion object of a given class will look like this:

TestClass::class.companionObject

Here's an example:

class TestClass {

    companion object {
        fun sayHello() = "Hello world"
    }
}

If you want to get the class that contains the companion, since the latter is always an inner class of the former,

class TestClass {

    companion object {
        fun whichIsMyParentClass() = this::class.java.declaringClass // It'll return TestClass
    }
}

And to further simplify, you'll also want to create an extension property:

import kotlin.reflect.KClass

val <T : Any> KClass<T>.companionClass get() =
    if (isCompanion)
        this.java.declaringClass
    else
        null

So, whenever you want to get the parent class of the companion object,

class TestClass {

    companion object {
        fun whichIsMyParentClass() = this::class.companionClass // It'll return TestClass
    }
}

The companion class itself has no reference to the actual class as you can see in this bytecode

public final class TestClass$Companion {

     private TestClass$Companion() { // <init> //()V
         <localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>

         L1 {
             aload0 // reference to self
             invokespecial java/lang/Object <init>(()V);
             return
         }
         L2 {
         }
     }

     public TestClass$Companion(kotlin.jvm.internal.DefaultConstructorMarker arg0) { // <init> //(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
         <localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>
         <localVar:index=1 , name=$constructor_marker , desc=Lkotlin/jvm/internal/DefaultConstructorMarker;, sig=null, start=L1, end=L2>

         L1 {
             aload0 // reference to self
             invokespecial TestClass$Companion <init>(()V);
             return
         }
         L2 {
         }
     }
}

The reference is only the other way around (see decompiled kotlin class)

public final class TestClass {
    public static final Companion companion = ...
}

So you can either do it as you just did by cutting off the .Companion part of the class name or you reference it by hard with TestClass::class.java (what is in my opinion no problem and the best solution)

Tags:

Kotlin