web-dev-qa-db-ja.com

静的変数をJavaからKotlinに変換します

次のコードをKotlinに変換しようとしていますが、Javaで使用されるクラス(Foo)の1つがまだあります。この変換を行う適切な方法は何ですか?

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

問題:

バークラスはC_IDまたはVALUESにアクセスできなくなりました(エラー:「プライベートアクセス」)

c_IDの前に「const」を置くと、機能しますが、VALUESで同じことはできません(「const」はプリミティブまたは文字列でのみ使用できます)

私がこれを行うべき別の方法はありますか(だからJavaコードとKotlinコードはFooのすべてにアクセスできます)?

23
Jeff Campbell

現在のセマンティクスは、 Kotlin Beta Candidate

@JvmFieldとオブジェクト

純粋なフィールド(get/setペアではなく)を生成する戦略をより予測可能にしました。これからは、_@JvmField_、lateinitまたはconstは、Javaクライアントにフィールドとして公開されます。古いバージョンは、ヒューリスティックを使用し、オブジェクトに静的フィールドを無条件に作成しました。

また、シングルトンインスタンスは、_INSTANCE$_ではなく、INSTANCEという名前でアクセスできるようになりました。

これと 参照 によると、JavaのKotlin objectのプロパティを操作する方法は3つあります。

  • _Foo.INSTANCE_を使用します。

    デフォルトでは、objectのプロパティはJavaの静的フィールドではありませんが、JavaはFooオブジェクトインスタンス-_Foo.INSTANCE_を介してプロパティにアクセスできます。

    したがって、式はFoo.INSTANCE.getC_ID()になります。

  • _@JvmStatic_アノテーションでプロパティをマークします:

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

    これにより、Foo.getC_ID()としてアクセス可能なFooインスタンスゲッターの代わりに、_C_ID_の静的ゲッターが生成されます。

  • プロパティ宣言で_@JvmField_注釈を使用します。

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

    これにより、Kotlinコンパイラは、プロパティの代わりにJavaの静的フィールドを生成します。その後、Javaで静的フィールドとしてアクセスできます:_Foo.C_ID_ 。

    ただし、例のallなどのフィールドをバッキングしないと、プロパティに対しては機能しません。

プリミティブについては、あなたが述べたように、constを使用できます。これは、Javaでの可視性の点で_@JvmField_と同じ効果があります。

ところで、メソッドに関して言えば、状況は同じであり、メソッドには_@JvmStatic_注釈があります。

35
hotkey

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を呼び出すことができます。

7

「kotlin way」の値にアクセスできるはずです。

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
Ron

定数のためだけに新しい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

0
sudesh