【问题标题】:Kotlin - what's the reasoning behind "const"Kotlin - “const”背后的原因是什么
【发布时间】:2018-08-31 18:15:33
【问题描述】:

valconst valhere有什么区别已经搞清楚了。

但我的问题是,为什么我们应该使用const 关键字?从生成的 Java 代码角度看没有区别。

这个 Kotlin 代码:

class Application

private val testVal = "example"

private const val testConst = "another example"

生成:

public final class ApplicationKt
{
    private static final String testVal = "example";
    private static final String testConst = "another example";
}

【问题讨论】:

  • 显式优于隐式。
  • 如果您在初始化后尝试将值分配给 const,编译器可能会将其视为可能的错误。通过定义一个常量,您是在告诉编译器(和开发人员,包括您自己)这个值不会改变。
  • @JamesB 如果您尝试将值分配给非const val,您认为会发生什么?
  • 我很惊讶没有人提到这一点。另一个很大的区别是编译器将内联一个常量。尝试在 Kotlin 代码中引用 testVal 和 testConst 以了解我的意思。

标签: kotlin constants


【解决方案1】:

在我看来,主要区别在于val 意味着不会为属性生成setter(但会生成getter)而不是值是常量,而const val 是常量(如Java 的private/public static final xxx)。

例子:

class Foo {
    private val testVal: String
        get() = Random().nextInt().toString()
}   

【讨论】:

    【解决方案2】:

    生成的代码并不总是相同。

    如果 testValtestConstpublic,则生成的代码将不同。 testVal 将是 privatepublic get,而 testConst 将是 public,没有任何吸气剂。所以const 避免生成getter。

    【讨论】:

    • 确实如此 - 对于公共领域,我们将拥有吸气剂。但这意味着对于private const val,我们应该被告知const 是一个冗余修饰符。
    【解决方案3】:

    文档中直接提到,testConst可以用在注解参数中,但testVal不能。

    更一般地说,const 保证你有一个 Java 意义上的常量变量,并且

    Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1), reachability (§14.21), and definite assignment (§16.1.1).

    【讨论】:

      【解决方案4】:

      在使用上也有区别。

      常量示例(Kotlin):

      class Constants {
          companion object {
              val EXAMPLE1 = "example1" // need companion and a getter
              const val EXAMPLE2 = "example2" // no getter, but companion is generated and useless
              @JvmField val EXAMPLE3 = "example3"; // public static final with no getters and companion
          }
      }
      

      如何使用(Java):

      public class UseConstants {
          public void method(){
              String ex1 = Constants.Companion.getEXAMPLE1();
              String ex2 = Constants.EXAMPLE2;
              String ex3 = Constants.EXAMPLE3;
          }
      }
      

      【讨论】:

        【解决方案5】:

        您看不到生成代码之间的区别,因为您的变量是private。否则结果将有getter 对应testVal

          public final class ApplicationKt {
               @NotNull
               private static final String testVal = "example";
               @NotNull
               public static final String testConst = "another example";
        
               @NotNull
               public static final String getTestVal() {
                  return testVal;
               }
            }
        

        所以在你的特定情况下它是相同的,除了你可以在annotations 中使用const 属性:

        const val testVal: String = "This subsystem is deprecated"
        @Deprecated(testVal) fun foo() { ... }
        

        【讨论】:

        • 确实如此 - 对于私有字段没有区别。但这意味着对于 private const val 我们应该被告知 const 是一个冗余修饰符。
        【解决方案6】:

        “Consts”是编译时常量,而“val”用于在运行时定义常量。 这意味着,“consts”永远不能分配给函数或任何类构造函数,而只能分配给字符串或原语。

        例子:

        const val NAME = "M Sakamoto"
        val PICon = getPI()
        
        fun getPI(): Double {
         return 3.14
        }
        
        fun main(args: Array<String>) {
          println("Name : $NAME")
          println("Value of PI : $PICon")
         }
        

        输出:

        Name : M Sakamoto
        Value of PI : 3.14
        

        【讨论】:

          猜你喜欢
          • 2011-06-20
          • 1970-01-01
          • 2020-01-26
          • 2016-03-31
          • 2021-11-01
          • 2010-10-03
          • 2018-02-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多