Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 1255 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Convert static variables from Java to Kotlin

#1
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)?
Reply

#2
You should be able to access the values "the 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) }
}
With as result:

ID
NAME

Process finished with exit code 0
Reply

#3
The current semantics come from [Kotlin Beta Candidate][1]:

> ###@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][2], 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.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#4
In your foo class you can put those properties and the method inside a companion object:


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


Then you can call Foo.getAll(), and Foo.C_ID, Foo.C_NAME and Foo.VALUES.
Reply

#5
it's better if you create new kotlin file just for constants.

create **Constants.kt** file and paste below code.

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

in your main activity you can access the constants by the constant name the android studio will automatically import the constants. here is my 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)
}
}
}

I was able to get log output successfully

[![logcat output][1]][1]


[1]:
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through