Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
443 views
in Technique[技术] by (71.8m points)

properties - Convert static variables from Java to Kotlin

I'm trying to convert the following code to Kotlin AND still have one of the classes (Foo) used by Java. What is the proper way of making this conversion?

Original 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();
    }
}

Auto conversion fo Foo to 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)
}

Problem:

Bar class can no longer access C_ID or VALUES (error: "private access")

if I put "const" in front of C_ID, it works... but I cannot do the same with VALUES ("const" can ONLY be used on primatives or String)

Is there a different way I should be doing this (so both Java code and Kotlin code can access everything in Foo)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The current semantics come from Kotlin Beta Candidate:

@JvmField and objects

We have made the strategy for generating pure fields (as opposed to get/set pairs) more predictable: from now on only properties annotated as @JvmField, lateinit or const are exposed as fields to Java clients. Older versions used heuristics and created static fields in objects unconditionally, which is against our initial design goal of having binary-compatibility-friendly APIs by default.

Also, singleton instances are now accessible by the name INSTANCE (instead of INSTANCE$).

According to this and to the reference, there are three ways of working with properties of a Kotlin object from Java:

  • Use Foo.INSTANCE.

    By default, properties of object won't be static fields for Java, but Java can access the properties through Foo object instance -- Foo.INSTANCE.

    So the expression will be Foo.INSTANCE.getC_ID().

  • Mark a property with @JvmStatic annotation:

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

    This will generate static getter for C_ID instead of Foo instance getter which will be accessible as Foo.getC_ID().

  • Use @JvmField annotation on property declaration:

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

    This will make Kotlin compiler generate a static field for Java instead of property. Then in Java you can access it as a static field: Foo.C_ID.

    But it won't work on properties without backing fields like all in your example.

For primitives, as you stated, one can use const which will have the same effect as @JvmField in terms of visibility in Java.

By the way, when it comes to methods, the situation is the same, and there is @JvmStatic annotation for them.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...