【问题标题】:Static data in KotlinKotlin 中的静态数据
【发布时间】:2016-09-25 17:28:56
【问题描述】:

请告诉我,这个例子有什么不同(在 Java 方面):

  1. object DefaultValues {
        val FILES_TO_DOWNLOAD = 100
    }
    

    class DefaultValues {
        companion object {
            val FILES_TO_DOWNLOAD = 100
        }
    }
    
  2. 没有类或对象包装器:

    const val DEFAULT_FILES_TO_DOWNLOAD = 100
    

    val DEFAULT_FILES_TO_DOWNLOAD = 100
    

真正的定义方式是什么?:

public static final int FILES_TO_DOWNLOAD = 100

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    您可以使用Kotlin bytecode viewer 找出这些选项被编译成什么。

    对于 Kotlin 1.0.2,编译后的字节码表明

    1. objectcompanion object 中的val 属性被编译成类内的private static final 字段:

       // access flags 0x1A
       private final static I FILES_TO_DOWNLOAD = 100
      

      还有一个getter,在引用属性时调用:

       // access flags 0x1019
       public final static synthetic access$getFILES_TO_DOWNLOAD$cp()I
      

      在 Java 中,getter 可以分别称为DefaultValues.INSTANCE.getFILES_TO_DOWNLOAD()DefaultValues.Companion.getFILES_TO_DOWNLOAD()

    2. const 顶级属性被编译为与(1) 相同的属性,唯一的区别是现在将字段和getter 放在FilenameKt 类中。

      但是顶级const val被编译成public static final字段:

      // access flags 0x19
      public final static I DEFAULT_FILES_TO_DOWNLOAD = 100
      

      当在对象中声明const val 时,将产生相同的公共静态最终字段。此外,如果将@JvmField 注释添加到(1) 中声明的属性,则可以获得相同的结果字节码。


    结论是,您可以在object 或顶层使用const@JvmField 定义public static final 字段。

    【讨论】:

    • 内部 var x; 怎么样?它是使 var 静态的吗?
    • @umitems, internal 只是一个可见性修饰符,与普通的公共var 的字节码应该没有太大区别。
    • 谢谢你的回答,我明白了。我只是尝试将 java 文件中的 public static int x 转换为 Kotlin 文件,然后我得到了 internal var x。
    • 这是否意味着在性能和字节码大小方面有任何差异?
    • @LouisCAD、const val@JvmField 比简单的val 更高效,但这主要是因为getter 调用,而JVM 非常擅长内联函数,尤其是运行时的getter .我想从长远来看,性能差异应该可以忽略不计(对于代码的非关键部分)。至于字节码大小,第二个选项也会产生更小的字节码,但无论如何你不太可能节省太多优化。
    猜你喜欢
    • 2021-03-21
    • 1970-01-01
    • 2018-08-28
    • 2018-07-03
    • 1970-01-01
    • 2016-09-12
    • 2015-03-28
    • 1970-01-01
    相关资源
    最近更新 更多