java - 在 Kotlin 中声明常量的所有方式之间的性能差异是什么?

标签 java kotlin jvm kotlinc

由于 Kotlin 不允许您像 Java 中的 static 成员那样直接在 class 中声明常量,因此我们有几种方法可以在 Kotlin 中实现.我的问题是,每个选项的性能成本是多少,哪个更便宜?我不想知道哪个更具可读性或被认为是最佳实践,我只想从性能的角度来看。

选项 1:使用伴随对象

所以代码看起来像这样:

class Thing {
    companion object {
        const val TAG = "Thing"
    }

   ...
}

在 Java 中是这样的:

public final class Thing {
   public static final String TAG = "Thing";
   public static final Thing.Companion Companion = new Thing.Companion((DefaultConstructorMarker)null);

   public static final class Companion {
      private Companion() {
      }

      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }

   ...
}

它创建了这个内部类 Companion 并实例化了它。这有多贵?

选项2:将其声明为顶级变量

所以这样:

const val TAG = "Thing"
class Thing {
   ...
}

变成这样:

public final class ThingKt {
   public static final String TAG = "Thing";
}

public final class Thing { ... }

它创建了一个带有static 成员的新类。这与使用对象来存储它有何不同?

选项 3:使用外部对象

像这样:

object ThingConstants {
    const val TAG = "Thing"
}

class Thing { ... }

在 Java 中是这样的:

public final class ThingConstants {
   public static final String TAG = "Thing";
   public static final ThingConstants INSTANCE;

   ...  // Private constructor
}

public final class Thing { ... }

与声明为顶级非常相似,除了创建的类有一个在私有(private)构造函数中初始化的 INSTANCE 字段。与使用顶级变量相比,这有多昂贵?

选项 4:删除 const 修饰符

所以你只需使用旧的val:

class Thing {
    val TAG = "Thing"
    
    ...
}

这对我来说是个谜。它不会创建任何额外的类,但也不会获得 const 修饰符的好处。这意味着该类的每个实例都将拥有自己的 TAG 实例,并为其生成 getter 和 setter,对吧?但我也是read JVM 将其优化为常量。所以这个选项比我最初想象的要多。

最佳答案

选项 1-3 在性能方面是相同的,因为它们都是 const,所以它们在编译时使用的任何地方都是内联的。

选项 4 不会为类的每个实例创建 String 的重复实例。相反,该类的每个实例都将有一个指向同一个共享实例的成员字段。就性能而言,从技术上讲,每次检索时都必须调用 getter 方法,但我希望现代 VM 能够在运行时优化该开销。

选项 1-3 确实会创建额外的 Java 类定义,因此它们的前期内存开销要多一些。但是,如果您在这些对象或顶级文件中已经有其他成员,那么无论如何您已经拥有了这些类。选项 4 在类中有一个额外的字段,因此如果类的实例很多,它可能会更重。

关于java - 在 Kotlin 中声明常量的所有方式之间的性能差异是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70526750/

相关文章:

spring-boot - Spring Boot 2.1.0使用Kotlin数据类更改安全性?

Kotlin 嵌套枚举类

java - 使用 Java 11 时 JDK_JAVA_OPTIONS 和 JAVA_TOOL_OPTIONS 有什么区别?

java - export JAVA_OPTS =""参数放在哪个文件?

java - Java 文档上的 ThreadPoolExecutor

java - 为什么service和dao的JDBC连接是一样的?

java - Kotlin 。如何格式化末尾为零的十进制数?

java - 如何将文本文件转换为arff文件?

java - 如何获取jtextpane中特定位置的前景色

java - 如何设置JVM存储MDMP文件的目录