Too*_*dos 36 java android kotlin kotlin-companion
我试图理解使用/不使用@JvmStatic与何时使用其中任何一个之间的区别.
所以,使用Kotlin和Java,我可以这样做:
TestKotlin.kt
class TestKotlin {
companion object {
val someString = "hello world"
}
}
Run Code Online (Sandbox Code Playgroud)
然后由Java调用,如下所示:
TestJava.java
public class TestJava {
String kotlinStaticString = TestKotlin.Companion.getSomeString();
}
Run Code Online (Sandbox Code Playgroud)
但是,有这个选项2:
TestKotlin.kt
V2
class TestKotlin {
companion object {
@JvmStatic // <-- notice the @JvmStatic annotation
val someString = "hello world"
}
}
Run Code Online (Sandbox Code Playgroud)
然后,从Java调用它,如下所示:
TestJava.java
V2
public class TestJava {
String kotlinStaticString = TestKotlin.getSomeString();
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:
谢谢!
yol*_*ole 42
@JvmStatic
注释的行为在文档中有详细说明.在阅读文档时,您应该假设它为您提供了所有重要信息,并且不存在文档中未提及的行为差异.
在这种情况下,文档说"如果使用此注释,编译器将在对象的封闭类中生成静态方法,并在对象本身中生成实例方法." 换句话说,注释的效果是它告诉编译器生成另一个方法.
文档是否提到行为或内存分配有任何差异?它不是.因此,可以安全地假设没有.
是否有偏好使用哪一个?通常,API在一个地方声明并在多个地方使用.如果您从Java调用方法,那么您应该将其声明为@JvmStatic
,因为@JvmStatic
在一个位置添加注释将允许您.Companion
在多个位置省略多个引用.
两者都创建一个伪静态单例对象,就像Java静态一样吗?这个问题没有意义,因为Java static不会创建"伪静态单例对象".如果在Java类中声明静态方法,然后调用此方法,则不会创建任何对象.
Yog*_*ity 21
Acompanion object
是一个class
名为的实数的实例Companion
。因此,当您从 Java 调用 Kotlin 代码时,Companion
首先会在幕后实例化该类的一个对象。为了理解这一点,让我们考虑一个简单的例子。
@JvmStatic
科特林代码
class Plant {
companion object {
fun waterAll() { }
}
}
Run Code Online (Sandbox Code Playgroud)
反编译的Java代码
public final class Plant {
public static final Plant.Companion Companion = new Plant.Companion();
public static final class Companion {
public final void waterAll() { }
private Companion() { }
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面简化的反编译 Java 代码中看到的那样,Companion
生成了一个名为的类来表示companion object
. 该类Plant
持有单个实例new Plant.Companion()
的类Plant.Companion
。该实例也被命名为Companion
. 这就是您需要使用以下命令调用companion object
Java 中的函数/属性的原因Plant.Companion
:
Plant.Companion.waterAll();
Run Code Online (Sandbox Code Playgroud)
@JvmStatic
科特林代码
class Plant {
companion object {
@JvmStatic
fun waterAll() { }
}
}
Run Code Online (Sandbox Code Playgroud)
反编译的Java代码
public final class Plant {
public static final Plant.Companion Companion = new Plant.Companion();
@JvmStatic
public static final void waterAll() { Companion.waterAll();}
public static final class Companion {
@JvmStatic
public final void waterAll() { }
private Companion() { }
}
}
Run Code Online (Sandbox Code Playgroud)
当您注释的功能companion object
与@JvmStatic
在科特林,一个纯粹的static
功能waterAll()
除了非静态函数生成waterAll()
。因此,现在您可以在没有Companion
名称的情况下调用该函数,这对 Java 来说更为惯用:
Plant.waterAll();
Run Code Online (Sandbox Code Playgroud)
在这两种情况下都会生成单例模式。如您所见,在这两种情况下,Companion
实例都持有单例对象new Plant.Companion()
,并且构造函数是private
为了防止多个实例。
Javastatic
关键字不会创建单例。仅当您companion object
在 Kotlin 中创建 a然后从 Java 中使用它时,您才会获得单例功能。要从 Java 获取单例,您需要编写单例模式,其代码类似于上面显示的反编译 Java 代码。
在内存分配方面没有性能增益或损失。原因是,正如您在上面的代码中看到的,static
生成的额外函数将其工作委托给非静态函数Companion.waterAll()
。这意味着,Companion
在两种情况下都需要创建实例,有@JvmStatic
和没有@JvmStatic
.
除了生成的额外方法之外,这两种设置的行为是相同的。在 Android 中,如果您担心方法数量,您可能需要注意这一点,因为为每个带注释的函数创建了一个额外的副本。
@JvmStatic
当您知道您的 Kotlin 代码不会在 Java 中使用时,您就不必担心添加@JvmStatic
注释。这使您的代码更干净。但是,如果您的 Kotlin 代码是从 Java 调用的,则添加注释是有意义的。这将防止您的 Java 代码在Companion
任何地方都被名称污染。
它不像任何一侧的附加关键字。如果您@JvmStatic
在一处添加,则可以防止Companion
在数千处(无论您调用该函数的任何地方)写入额外的单词。这对库创建者特别有用,如果他们添加@JvmStatic
到他们的 Kotlin 库中,该库的用户将不必Companion
在他们的 Java 代码中使用这个词。
就是这样!希望这有助于更清晰地了解@JvmStatic
.
Mad*_*ddy 13
您将函数放置在“伴随对象”中。
所以java代码是这样的:
class DemoClass {
public static int myMethod() { return 1; }
}
Run Code Online (Sandbox Code Playgroud)
会变成
class DemoClass {
companion object {
fun myMethod() : Int = 1
}
}
Run Code Online (Sandbox Code Playgroud)
然后您可以在 Kotlin 代码中使用它作为
DemoClass.myMethod();
Run Code Online (Sandbox Code Playgroud)
但是在 Java 代码中,您需要将其称为
DemoClass.Companion.myMethod();
Run Code Online (Sandbox Code Playgroud)
(这也适用于 Kotlin 内部。)
如果您不想指定Companion
位,您可以添加@JvmStatic
注释或命名您的伴生类。
从文档:
伴随对象
类中的对象声明可以用伴随关键字标记:
Run Code Online (Sandbox Code Playgroud)class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
可以通过简单地使用类名作为限定符来调用伴生对象的成员:
Run Code Online (Sandbox Code Playgroud)val instance = MyClass.create()
...
但是,在 JVM 上,如果使用
@JvmStatic
注释,您可以将伴随对象的成员生成为真正的静态方法和字段。有关更多详细信息,请参阅 Java 互操作性部分。
添加@JvmStatic
注释看起来像这样
class DemoClass {
companion object {
@JvmStatic
fun myMethod() : Int = 1;
}
}
Run Code Online (Sandbox Code Playgroud)
然后 a 将作为一个真正的 Java 静态函数存在,可以从 Java 和 kotlin 作为DemoClass.myMethod()
.
如果只是因为Companion
名称不喜欢它,那么您还可以为伴随对象提供一个显式名称,如下所示:
class DemoClass {
companion object Blah {
fun myMethod() : Int = 1;
}
}
Run Code Online (Sandbox Code Playgroud)
这将让您以相同的方式从 Kotlin 调用它,但是从 java like DemoClass.Blah.myMethod()
(它也可以在 Kotlin 中工作)。
归档时间: |
|
查看次数: |
11540 次 |
最近记录: |