[Android]Kotlinの「@JvmStatic」アノテーションとは

Kotlinでは、どのクラスからでもインスタンスを経由せずにアクセスできるメソッド(クラスメソッド)を作る方法の1つに「companion object」というものがあります。

例えば、こんな感じでcompanion objectの中にnewInstanceメソッドを設定すると、

class KotlinFragment : Fragment() {
    
  ********

    companion object {
     //↓これ
        fun newInstance(param1: String, param2: String) = 
                KotlinFragment().apply {
                    arguments = Bundle().apply {
                        putString(ARG_PARAM1, param1)
                        putString(ARG_PARAM2, param2)
                    }
                }
    }
}

 

他のKotlinファイルから呼び指す際に、KotlinFragmentのインスタンスを経由せずに、こんな感じでアクセスすることが出来ます。

 

companion object内に作ったメソッドはJavaでいう「static」メソッドではない

まさに、これはJavaでいう「staticメソッド(クラスメソッド)」という感じになるはずなのですが、ところがどっこいしょ。

他のJavaファイルからは、上のような感じで呼び出すことができず、

 

Companionクラスを経由しないと呼び出すことができないのです。

 

 

なんでや?

Kotlinのcompanion object内のメンバ(プロパティ・メソッド)は、一見Javaのstaticのように見えますが、実行時にインスタンス化されるので、インターフェースの実装なども出来るという点で、「static」とは異なる。

ということらしいです(companion objectは実際のオブジェクトのシングルトンインスタンスだそうです)。

こんな感じで。

interface Factory<T> {
    fun create(): T
}

class MyClass {
    companion object : Factory<MyClass> { ← Factoryインターフェースを実装している
        override fun create(): MyClass = MyClass()
    }
}

Note that, even though the members of companion objects look like static members in other languages, at runtime those are still instance members of real objects, and can, for example, implement interfaces:

(companion object内のメンバ(プロパティ・メソッド)は、他のプログラミング言語(Java等)における『static(静的な)』メンバのように見えるが、Kotlinでは、実行時におけるこれらのメンバは実オブジェクトのインタンスメンバ(動的メンバ)であり、たとえばインターフェースを実装することもできる)

https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects

 

ほなどないしたらエエねん!?

「@JvmStatic」アノテーションをつけたらエエということらしいです。

However, on the JVM you can have members of companion objects generated as real static methods and fields, if you use the @JvmStatic annotation.

(しかしながら、JVM(Java Virtual Machine)では、companion objectのメンバを本当にstaticなフィールドやメソッド(メンバ)として生成することもでき、その際は@JvmStaticアノテーションをつければよい)

https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects

 

ですので、こうしてやると、

class KotlinFragment : Fragment() {
    
  ********

    companion object {
    @JvmStatic //←こいつ
        fun newInstance(param1: String, param2: String) = 
                KotlinFragment().apply {
                    arguments = Bundle().apply {
                        putString(ARG_PARAM1, param1)
                        putString(ARG_PARAM2, param2)
                    }
                }
    }
}

 

Javaファイルからでも、ちゃんとstaticメソッドとしてアクセスできるようになりました。

 

ということです。

詳しい解説は下の動画をご覧ください。それよりもっと詳しく知りたい場合はこれを読めばいいかもです。

 

こんな記事も読まれています

みんプロにかける想い

  1. こんな無駄な苦労をするのはぼくで最後にしたい(ぼくがプログラミング講座をはじめたわけ)

  2. プログラミングはみんなのもの!(プログラミングの醍醐味である「楽しさ」を伝えたい)

  3. ぼくが別に言う必要のない挫折の黒歴史をあえてさらけ出している理由(自分の中にある「ブロック」を外すきっかけにしてほしい)

  4. プログラミングは手段の1つに過ぎない(目的は自分のアイデアを形にすること)

  5. プログラミングを通じて「やわらかい世の中」を作りたい(ぼくがプログラミング講座をやっている本当の理由②)

みんプロ作成アプリ




みんプロ代表の黒歴史


TOP