TL;DR
-
::Constructorというような形で取得したKFunctionはkotlin.jvm.internal.FunctionReferenceにキャストできる1 -
FunctionReferenceからはkotlin-reflect無しでも様々な情報を得ることができる - ただし、パッケージ名にも有る通り、
internalな(= 外部から参照されることを想定していない)APIを参照することになるため、Kotlinの更新で壊れる可能性が有る点には注意が必要- 加えて、一部のメソッドは
kotlin-reflect無しで呼び出すと実行時エラーになる点にも注意が必要
- 加えて、一部のメソッドは
本文
基本的にキャストするだけで全ての情報が取得できるので、サンプルコードとコメントだけで詳細な説明は省きます。
import kotlin.jvm.internal.ClassBasedDeclarationContainer
import kotlin.jvm.internal.FunctionReference
// Sampleクラスのコンストラクタを使って呼び出す例
readInfoSample(::Sample as FunctionReference)
fun readInfoSample(ref: FunctionReference) {
// メソッドの名前や引数の情報(signature形式)
val name: String = ref.name
val signature: String = ref.signature
// methodでいう所のインスタンスパラメータ
// objectや、${instance}::${method}の形で取得した場合、当該のインスタンスが返ってくる
// インスタンスパラメータが設定されない/されていないメソッドの場合、FunctionReference.NO_RECEIVERのインスタンスが返ってくる
val boundReceiver: Any = ref.boundReceiver
// このFunctionReferenceを定義するclassまたはファイルの情報
// 試した限りではnullやClassBasedDeclarationContainer以外の型にならない
val owner: ClassBasedDeclarationContainer = ref.owner!! as ClassBasedDeclarationContainer
// java classも読み出せる
val jClass: Class<*> = owner.jClass
}
手元で検証した限り、コンストラクタ、インスタンス関数、トップレベル関数などについてはこの方法で情報を読み出せるようでした。
ただし、冒頭に記載した点には注意が必要です。
補足
jClassからMetadataアノテーションを取得し、kotlinx-metadata-jvmで解析することで、より詳細な情報を得ることもできます。
-
KClassなどから読み出すパターンは想定していません。また、その場合取得できるのはKFunctionImplとなるため、この記事で紹介する方法は使えない可能性が有ります。 ↩