首页 文章

将静态变量从Java转换为Kotlin

提问于
浏览
22

我正在尝试将以下代码转换为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”只能用于primatives或String)

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

4 回答

  • 34

    目前的语义来自Kotlin Beta Candidate

    @JvmField和objects我们已经使生成纯字段(与get / set对相对)的策略更具可预测性:从现在开始,只有注释为@JvmField,lateinit或const的属性才会作为字段暴露给Java客户端 . 较旧的版本使用启发式方法并无条件地在对象中创建静态字段,这违反了我们的默认初始设计目标,即具有二进制兼容性友好的API . 此外,现在可以通过名称INSTANCE(而不是INSTANCE $)访问单例实例 .

    根据这个和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 而不是 Foo 实例getter生成静态getter,它将作为 Foo.getC_ID() 访问 .

    • 在属性声明中使用 @JvmField 注释:
    object Foo {
        @JvmField val C_ID = "ID"
        //...
    }
    

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

    但是,如果没有像示例中的 all 这样的字段,它将不适用于属性 .

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

    顺便说一句,当涉及到方法时,情况是相同的,并且它们有 @JvmStatic 注释 .

  • 7

    在你的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 .

  • 0

    您应该能够访问“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
    
  • 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将自动导入常量 . 这是我的mainActivity:

    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)
            }
        }
    }
    

    我能够成功获得日志输出

    logcat output

相关问题