@JvmStaticの使用の有無の違いと、どちらを使用すべきかを理解しようとしています。
したがって、KotlinとJavaを使用すると、次のことができます。
TestKotlin.kt
class TestKotlin {
companion object {
val someString = "hello world"
}
}
次のように、Javaによって呼び出されます。
TestJava.Java
public class TestJava {
String kotlinStaticString = TestKotlin.Companion.getSomeString();
}
しかし、その後、このオプション2があります:
TestKotlin.kt
v2
class TestKotlin {
companion object {
@JvmStatic // <-- notice the @JvmStatic annotation
val someString = "hello world"
}
}
次に、次のようにJavaから呼び出します。
TestJava.Java
v2
public class TestJava {
String kotlinStaticString = TestKotlin.getSomeString();
}
だから私の質問は:
ありがとう!
@JvmStatic
アノテーションの動作については、 ドキュメント で詳しく説明されています。ドキュメントを読むとき、すべての重要な情報が提供され、ドキュメントに記載されていない動作の違いは存在しないと想定する必要があります。
この場合、ドキュメントには次のように記載されています。
この注釈を使用すると、コンパイラはオブジェクトの包含クラスの静的メソッドとオブジェクト自体のインスタンスメソッドの両方を生成します。
つまり、注釈の効果は、コンパイラーに追加のメソッドを生成するように指示することです。
ドキュメントには、動作またはメモリ割り当てに違いがあると記載されていますか?ありません。したがって、何もないと仮定しても安全です。
どちらを使用するかについての好みはありますか?通常、APIは1つの場所で宣言され、複数の場所で使用されます。 Javaからメソッドを呼び出す場合は、@JvmStatic
アノテーションを1か所に追加すると複数の@JvmStatic
参照を省略することができるため、.Companion
として宣言する必要があります。 。
Java staticのように、両方とも擬似静的シングルトンオブジェクトを作成しますか?Java staticは「擬似静的シングルトンオブジェクト」。Javaクラスで静的メソッドを宣言し、このメソッドを呼び出した場合、オブジェクトは作成されません。
関数を「コンパニオンオブジェクト」に配置します。
Javaこのようなコード:
_class DemoClass {
public static int myMethod() { return 1; }
}
_
となります
_class DemoClass {
companion object {
fun myMethod() : Int = 1
}
}
_
その後、Kotlinコード内から次のように使用できます。
_DemoClass.myMethod();
_
ただし、Javaコード内では、次のように呼び出す必要があります。
_DemoClass.Companion.myMethod();
_
(これはKotlin内でも動作します。)
Companion
ビットを指定する必要がない場合は、_@JvmStatic
_注釈を追加するか、コンパニオンクラスに名前を付けることができます。
docs から:
コンパニオンオブジェクト
クラス内のオブジェクト宣言は、コンパニオンキーワードでマークできます。
_class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
_コンパニオンオブジェクトのメンバーは、単にクラス名を修飾子として使用して呼び出すことができます。
_val instance = MyClass.create()
_...
ただし、JVMでは、_
@JvmStatic
_注釈を使用すると、実際の静的メソッドおよびフィールドとして生成されるコンパニオンオブジェクトのメンバーを持つことができます。詳細については、Java interoperabilityセクションを参照してください。
_@JvmStatic
_アノテーションの追加は次のようになります
_class DemoClass {
companion object {
@JvmStatic
fun myMethod() : Int = 1;
}
}
_
そして、aは、実際のJava静的関数として、Javaとkotlinの両方からDemoClass.myMethod()
としてアクセス可能)として存在します。
Companion
の名前が嫌いな場合は、コンパニオンオブジェクトの明示的な名前を次のように指定することもできます。
_class DemoClass {
companion object Blah {
fun myMethod() : Int = 1;
}
}
_
同じ方法でKotlinから呼び出すことができますが、Java like DemoClass.Blah.myMethod()
(Kotlinでも動作します)から)。
Kotlinでは、companion
オブジェクトを使用して静的動作を模倣できます。呼び出しはJavaの静的呼び出しのように見えますが、“Companion“
はifの一部ではありません。 Java=)で使用する場合、@JvmStatic
が適用されない限り、companion
オブジェクトに名前を付ける必要があります。
TestKotlin.getSomeString() //this should be preferred whenever possible
docs に記載されています:
コンパニオンオブジェクト
クラス内のオブジェクト宣言は、コンパニオンキーワードでマークできます。
class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
コンパニオンオブジェクトのメンバーは、単にクラス名を修飾子として使用して呼び出すことができます。
val instance = MyClass.create()
...
ただし、
@JvmStatic
注釈を使用する場合、JVMでは、実際の静的メソッドおよびフィールドとして生成されたコンパニオンオブジェクトのメンバーを持つことができます。詳細については、Java interoperabilityセクションを参照してください。
前述のようにadditionalメソッドが生成されることに注意してください here :
この注釈を使用すると、コンパイラはオブジェクトの包含クラスの静的メソッドとオブジェクト自体のインスタンスメソッドの両方を生成します。
exampleを見てみましょう:
次のクラス
class Outer {
companion object {
fun callMe() = ""
}
}
バイトコードレベルでは次のようになります。ここではJava code:
@Metadata(...)
public final class Outer {
public static final Outer.Companion Companion = new Outer.Companion((DefaultConstructorMarker)null);
@Metadata(...)
public static final class Companion {
@NotNull
public final String callMe() {
return "";
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
ただし、@JvmStatic
がcallMe
メソッドに適用されている場合、バイトコードは次のように変更されます。
@Metadata(...)
public final class Outer {
public static final Outer.Companion Companion = new Outer.Companion((DefaultConstructorMarker)null);
@JvmStatic
@NotNull
public static final String callMe() {
return Companion.callMe();
}
@Metadata(...)
public static final class Companion {
@JvmStatic
@NotNull
public final String callMe() {
return "";
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
callMe
の一部が生成されると、静的なOuter
関数が正しく文書化されます:
@JvmStatic
@NotNull
public static final String callMe() {
return Companion.callMe();
}