【问题标题】:Convert static variables from Java to Kotlin将静态变量从 Java 转换为 Kotlin
【发布时间】:2016-05-09 04:40:29
【问题描述】:

我正在尝试将以下代码转换为 Kotlin,并且仍然有 Java 使用的类 (Foo) 之一。进行这种转换的正确方法是什么?

原始Java:

public class Foo {
   public static final String C_ID = "ID";
   public static final String C_NAME = "NAME";
   public static final String[] VALUES = {"X", "Y", "Z"};

   public static String[] getAll() {
       return new String[] {C_ID, C_NAME};
   }
}

public class Bar {
    public void doStuff() {
        String var1 = Foo.C_ID;
        String[] array1 = Foo.VALUES;
        String[] array2 = Foo.getAll();
    }
}

Foo 到 Kotlin 的自动转换

object Foo {
    val C_ID = "ID"
    val C_NAME = "NAME"
    val VALUES = arrayOf("X", "Y", "Z")

    val all: Array<String>
        get() = arrayOf(C_ID, C_NAME)
}

问题:

Bar 类不能再访问 C_ID 或 VALUES(错误:“私人访问”)

如果我将“const”放在 C_ID 前面,它可以工作......但我不能对 VALUES 做同样的事情(“const”只能用于基本体或字符串)

我应该以不同的方式执行此操作(因此 Java 代码和 Kotlin 代码都可以访问 Foo 中的所有内容)?

【问题讨论】:

  • 虽然const val 可能有你需要的效果,但它的用途不同(编译器时间常数),不应该将它用于互操作。

标签: properties static field kotlin


【解决方案1】:

最好为常量创建新的 kotlin 文件。

创建 Constants.kt 文件并粘贴以下代码。

object Constants {
val C_ID = "ID"
val C_NAME = "NAME"
val VALUES = arrayOf("X", "Y", "Z")

val all: Array<String>
    get() = arrayOf(C_ID, C_NAME)
}

在您的主要活动中,您可以通过常量名称访问常量,android studio 将自动导入常量。这是我的主要活动:

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.example.architecturecompintro.Constants.C_ID
import com.example.architecturecompintro.Constants.C_NAME
import com.example.architecturecompintro.Constants.VALUES
import com.example.architecturecompintro.Constants.all

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val TAG = "info"

        Log.i(TAG, C_ID)
        Log.i(TAG,C_NAME)

        for(item in VALUES) {
            Log.i(TAG,item)
        }
        val arrayItem = all

        for(item in arrayItem) {
            Log.i(TAG,item)
        }
    }
}

我能够成功获取日志输出

【讨论】:

    【解决方案2】:

    在您的 foo 类中,您可以将这些属性和方法放在一个伴生对象中:

    class Foo {
    
      companion object {
         val C_ID:String = "ID"
         val C_NAME:String = "NAME"
         @JvmField val VALUES = arrayOf("X", "Y", "Z")
    
         fun getAll():Array<String> {
            return arrayOf(C_ID, C_NAME)
         }
      }
    }
    

    然后你可以调用 Foo.getAll() 和 Foo.C_ID、Foo.C_NAME 和 Foo.VALUES。

    【讨论】:

      【解决方案3】:

      当前语义来自Kotlin Beta Candidate

      @JvmField 和对象

      我们使生成纯字段的策略(相对于 get/set 对)更可预测:从现在开始,只有注释为 @JvmFieldlateinitconst 的属性作为字段公开到 Java 客户端。旧版本使用启发式算法并无条件地在对象中创建静态字段,这违背了我们最初的设计目标,即默认提供二进制兼容友好的 API。

      此外,现在可以通过名称 INSTANCE(而不是 INSTANCE$)访问单例实例。

      根据 this 和 reference,有三种方法可以使用 Java 中的 Kotlin object 的属性:

      • 使用Foo.INSTANCE

        默认情况下,object 的属性不会是 Java 的静态字段,但 Java 可以通过 Foo 对象实例 -- Foo.INSTANCE 访问属性。

        所以表达式将是Foo.INSTANCE.getC_ID()

      • @JvmStatic注解标记一个属性:

        object Foo {
            @JvmStatic val C_ID = "ID"
            //...
        }
        

        这将为C_ID 生成静态getter,而不是Foo 实例getter,后者可作为Foo.getC_ID() 访问。

      • 在属性声明中使用@JvmField注解:

        object Foo {
            @JvmField val C_ID = "ID"
            //...
        }
        

        这将使 Kotlin 编译器为 Java 生成静态字段而不是属性。 然后在 Java 中,您可以将其作为静态字段访问:Foo.C_ID

        但在您的示例中,如果没有像 all 这样的支持字段,它将无法在属性上工作。

      对于原语,如您所说,可以使用const,就Java 中的可见性而言,它与@JvmField 具有相同的效果。

      对了,说到方法,情况也是一样的,有@JvmStatic注解给他们。

      【讨论】:

        【解决方案4】:

        您应该能够以“kotlin 方式”访问值:

        object Foo {
        val C_ID = "ID"
        val C_NAME = "NAME"
        val VALUES = arrayOf("X", "Y", "Z")
        
        val all: Array<String>
            get() = arrayOf(C_ID, C_NAME)
        }
        
        fun main(args: Array<String>) {
            Foo.all.forEach { it->println(it) }
        }
        

        结果:

        ID
        NAME
        
        Process finished with exit code 0
        

        【讨论】:

        • 问题是关于在 Java 中访问 Kotlin object 的部分内容,“Kotlin 方式”是什么意思,为什么 C_IDC_NAME 应该可以通过数组访问?跨度>
        • 该操作有一个 val "all",它有一个 arrayOf 作为 getter。我决定在我的示例代码中使用它。我不是 kotlin 专家,但我会这样做
        • 抱歉,没有注意到all val。尽管问题似乎更多地是关于 Java 互操作。
        猜你喜欢
        • 1970-01-01
        • 2014-09-05
        • 1970-01-01
        • 2021-07-24
        • 2018-11-26
        • 1970-01-01
        • 2018-09-14
        • 1970-01-01
        • 2019-09-05
        相关资源
        最近更新 更多