How do you make Kotlin static variables and functions for Java? - java

Since Google made Kotlin a first class language for Android, there has been an increase in questions relating to how to perform certain things in Kotlin, "Java-esque" style. The most common ones are how to make static variables in Kotlin. So how do you make Kotlin static variables and functions?

You can't. Well, at least in a pure Kotlin project.
Kotlin has no notion of static. The way static works in a Kotlin-Java project is by use of annotations on the Kotlin classes to tell the JVM that the desired variable/function should be exposed as a static to Java classes.
The following is an example guide for Kotlin-Java static interop (answer originally posted in What is the equivalent of Java static methods in Kotlin?):
Scenario 1: Creating a static method in Kotlin for Java
Kotlin
#file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits
class KotlinClass {
companion object {
//This annotation tells Java classes to treat this method as if it was a static to [KotlinClass]
#JvmStatic
fun foo(): Int = 1
//Without it, you would have to use [KotlinClass.Companion.bar()] to use this method.
fun bar(): Int = 2
}
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
println(KotlinClass.foo()); //Prints "1"
println(KotlinClass.Companion.bar()); //Prints "2". This is the only way to use [bar()] in Java.
println(KotlinClass.Companion.foo()); //To show that [Companion] is still the holder of the function [foo()]
}
//Because I'm way to lazy to keep typing [System.out], but I still want this to be compilable.
void println(Object o) {
System.out.println(o);
}
}
This answer provides more depth than this, and should definitely be referenced for this scenario.
This next scenario handles creating static fields in Kotlin so that Java doesn't have to keep calling KotlinClass.foo() for those cases where you don't want a static function.
Scenario 2: Creating a static variable in Kotlin for Java
Kotlin
#file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits
class KotlinClass {
companion object {
//This annotation tells Kotlin to not generate the getter/setter functions in Java. Instead, this variable should be accessed directly
//Also, this is similar to [#JvmStatic], in which it tells Java to treat this as a static variable to [KotlinClass].
#JvmField
var foo: Int = 1
//If you want something akin to [final static], and the value is a primitive or a String, you can use the keyword [const] instead
//No annotation is needed to make this a field of [KotlinClass]. If the declaration is a non-primitive/non-String, use #JvmField instead
const val dog: Int = 1
//This will be treated as a member of the [Companion] object only. It generates the getter/setters for it.
var bar: Int = 2
//We can still use [#JvmStatic] for 'var' variables, but it generates getter/setters as functions of KotlinClass
//If we use 'val' instead, it only generates a getter function
#JvmStatic
var cat: Int = 9
}
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
//Example using #JvmField
println(KotlinClass.foo); //Prints "1"
KotlinClass.foo = 3;
//Example using 'const val'
println(KotlinClass.dog); //Prints "1". Notice the lack of a getter function
//Example of not using either #JvmField, #JvmStatic, or 'const val'
println(KotlinClass.Companion.getBar()); //Prints "2"
KotlinClass.Companion.setBar(3); //The setter for [bar]
//Example of using #JvmStatic instead of #JvmField
println(KotlinClass.getCat());
KotlinClass.setCat(0);
}
void println(Object o) {
System.out.println(o);
}
}
One of the great features about Kotlin is that you can create top level functions and variables. This makes it greate to create "classless" lists of constant fields and functions, which in turn can be used as static functions/fields in Java.
Scenario 3: Accessing top level fields and functions in Kotlin from Java
Kotlin
//In this example, the file name is "KSample.kt". If this annotation wasn't provided, all functions and fields would have to accessed
//using the name [KSampleKt.foo()] to utilize them in Java. Make life easier for yourself, and name this something more simple
#file:JvmName("KotlinUtils")
package com.frybits
//This can be called from Java as [KotlinUtils.TAG]. This is a final static variable
const val TAG = "You're it!"
//Since this is a top level variable and not part of a companion object, there's no need to annotate this as "static" to access in Java.
//However, this can only be utilized using getter/setter functions
var foo = 1
//This lets us use direct access now
#JvmField
var bar = 2
//Since this is calculated at runtime, it can't be a constant, but it is still a final static variable. Can't use "const" here.
val GENERATED_VAL:Long = "123".toLong()
//Again, no need for #JvmStatic, since this is not part of a companion object
fun doSomethingAwesome() {
println("Everything is awesome!")
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
println(KotlinUtils.TAG); //Example of printing [TAG]
//Example of not using #JvmField.
println(KotlinUtils.getFoo()); //Prints "1"
KotlinUtils.setFoo(3);
//Example using #JvmField
println(KotlinUtils.bar); //Prints "2". Notice the lack of a getter function
KotlinUtils.bar = 3;
//Since this is a top level variable, no need for annotations to use this
//But it looks awkward without the #JvmField
println(KotlinUtils.getGENERATED_VAL());
//This is how accessing a top level function looks like
KotlinUtils.doSomethingAwesome();
}
void println(Object o) {
System.out.println(o);
}
}
Another notable mention that can be used in Java as "static" fields are Kotlin object classes. These are zero parameter singleton classes that are instantiated lazily on first use. More information about them can be found here: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
However, to access the singleton, a special INSTANCE object is created, which is just as cumbersome to deal with as Companion is. Here's how to use annotations to give it that clean static feel in Java:
Scenario 4: Using object classes
Kotlin
// There is no more need for the #file:JvmName() annotation. The object class below already handles the proper naming.
//This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits
object KotlinClass { //No need for the 'class' keyword here.
//Direct access to this variable
const val foo: Int = 1
//Tells Java this can be accessed directly from [KotlinClass]
#JvmStatic
var cat: Int = 9
//Just a function that returns the class name
#JvmStatic
fun getCustomClassName(): String = this::class.java.simpleName + "boo!"
//Getter/Setter access to this variable, but isn't accessible directly from [KotlinClass]
var bar: Int = 2
fun someOtherFunction() = "What is 'INSTANCE'?"
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
println(KotlinClass.foo); //Direct read of [foo] in [KotlinClass] singleton
println(KotlinClass.getCat()); //Getter of [cat]
KotlinClass.setCat(0); //Setter of [cat]
println(KotlinClass.getCustomClassName()); //Example of using a function of this 'object' class
println(KotlinClass.INSTANCE.getBar()); //This is what the singleton would look like without using annotations
KotlinClass.INSTANCE.setBar(23);
println(KotlinClass.INSTANCE.someOtherFunction()); //Accessing a function in the object class without using annotations
}
void println(Object o) {
System.out.println(o);
}
}

Related

Use property getter method reference for functional (SAM) interface variables

I want to pass a property getter method reference as one of the function arguments, and have that argument be of my own functional interface type, but ran into an issue.
Here's a stripped down minimal reproducible case, I changed the variable from an argument into a property, but the issue is the same.
class Foo {
val bar: Bar? = null
}
class Bar
fun interface FooBarSelector {
fun select(foo: Foo): Bar?
}
class KotlinClass() {
val selector: FooBarSelector = Foo::bar
}
This doesn't compile, Foo::bar is underlined and the error is
Type mismatch.
Required: FooBarSelector
Found: KProperty1<Foo, Bar?>
I tried to look this up, found similar questions about SAM conversions, but they were a bit different and I don't think any of them referred specifically to property getters.
I found that the issue can be solved by doing one of the following:
Remove the explicit type, or replace it with the suggested KProperty1. Not an option, I want to preserve my type.
Replace the method reference with FooBarSelector { it.bar }. Far from ideal, but better than the first option.
Why does this happen and are there any other options? I am new to Kotlin, but not Java.
Kotlin version used is 1.7.20
EDIT:
Here's my original goal: accept a FooBarSelector as an argument, and by default point it at a property getter:
fun doSomething(
selector: FooBarSelector = Foo::bar //doesn't compile
) {
}
Your code with the lambda is fine, but you may prefer this syntax for the same thing:
class KotlinClass() {
val selector = FooBarSelector(Foo::bar)
}
Explanation:
Kotlin function references are more explicit about types than in Java, because function references are a first-class object type. When you want to use a function reference as a functional interface instance, you must convert it. This can be done automatically by the compiler using SAM conversion.
SAM conversion only works when passing a function reference as an argument to a function that has a parameter with a functional interface type. So, it doesn't directly work when assigning to a property.
But Kotlin implicitly provides higher order functions for functional interfaces that allow you to pass a function reference that will convert it into an interface instance. The implicit function is named after the interface, so it looks like a constructor call.
In the above code, the implicit functional interface "constructor" is inline, so there is no intermediate functional object allocated in the compiled code. This compiles to the same thing you would get in Java with a direct method reference.
I am not 100% sure what you are expecting but consider this example:
class Foo(
val bar: Bar
)
data class Bar(
val value: String
)
interface FooBarSelector {
fun select(foo: Foo): Bar {
return foo.bar
}
}
class FooBarCustomSelector: FooBarSelector {
override fun select(foo: Foo): Bar {
return Bar("I don't care about which Foo was passed. I'll return my own Bar")
}
}
class KotlinClass(val selector: (Foo) -> Bar = Foo::bar)
fun main(args: Array<String>) {
val kotlinClassWithDefaultSelector = KotlinClass()
val kotlinClassWithCustomSelector = KotlinClass(FooBarCustomSelector()::select)
val foo = Foo(Bar("Bar1"))
println("kotlinClassWithDefaultSelector: ${kotlinClassWithDefaultSelector.selector(foo)}")
println("kotlinClassWithCustomSelector: ${kotlinClassWithCustomSelector.selector(foo)}")
}
This would print:
kotlinClassWithDefaultSelector: Bar(value=Bar1)
kotlinClassWithCustomSelector: Bar(value=I don't care about which Foo was passed. I'll return my own Bar)

How to set value without setter method?

In the below code snippet how can I set the value of a and b without using the setter method? Is it possible? Can I call the private constructor in the public constructor?
public class ABC {
private int a;
private int b;
public ABC() {
}
private ABC(int a, int b) {
this.a = a;
this.b = b;
}
}
ABC abc = new ABC();
You can use Java reflection, but this is considered to be bad practice and should be avoided. However, if you really need to:
ABC abc = new ABC();
Field abc_a = abc.getClass().getDeclaredField("a");
abc_a.setAccessible(true);
abc_a.set(abc, 20);
Explanation
Field abc_a = abc.getClass().getDeclaredField("a");
In java, there is a set of tools called Reflection, whose intended use is to allow for fields in classes to be dynamically set. A practical use of this is the GSON library, which reads JSON and automatically fills in the corresponding values in a class.
Every class has a Class object to assist with reflection, and every instance of an object has a method called getClass(). Calling this method will give you the Class object representing that class and using that, you can then invoke the getDeclaredField(fieldName) method which will return a Field object that allows you to do a variety of things to that field, one of which is setting the value.
abc_a.setAccessible(true);
Because the field being referenced to is private, this must be invoked to allow it to be accessed. If it was public, this step could be omitted.
abc_a.set(abc, 20);
This finally changes the value of the field a in the ABC class. The first parameter is the object you wish to change the value of, and the second parameter is the new value. Note that Field objects don't store class information, so if you wished to change the value of a different instance of ABC, you could use the same Field object and just change the first parameter.
If I understand you correctly, your actual question is
Can I call the private constructor in the public constructor?
and nothing really related to setters.
Yes, you can call one constructor from another. In your example code this would look like this:
public ABC() {
this(0, 0); // initialze a and b via the private constructor
}

Getting getters (or methods or properties) list in generic class with Kotlin

I can't figure out how should i deal with generics in kotlin.
I'm writing a history class for changes made on generic objects, which should get any type of class as parameter: after that, I would compare the old object values with the new object values, and if I found a difference, I'll write that in my data class.
I've succedeed doing that with java with bean.getClass().getMethods();, but I want to trying move to Kotlin.
class ChangeHistoryUtils<T> (val originalBean : T, username : String , var modifiedBean: T? = null) {
data class ChangeHistory(val username: String, val fieldName : String,
val oldValue : String , val newValue : String , val date : LocalDate = LocalDate.now())
fun compareBeans(){
//how to get all originalBean getters and its values?
}
}
I'm actually stuck here: how should obtain all the getters in my T object?
Let's guess i'll receive a class which with 10 getters, I want to call all these 10 getters in originalBean, and comparing its value with the ones in modifiedBean. If different, I will write it in my ChangeHistory
Thanks
You need to ensure that T itself is not a nullable type, i.e. use something like where T : Any on the class declaration, e.g.:
class ChangeHistoryUtils<T> (originalBean : T, username : String , modifiedBean: T? = null) where T : Any
If you do that you can afterwards just access the methods as you did in Java, e.g. if you just want to reuse the code you already have:
fun compareBeans(){
originalBean::class.java.methods // this is actually your originalBean.getClass().getMethods() !
// just print the methods for now...
.forEach(::println)
}
But as you are using Kotlin you may rather want to use the Kotlin approach then, e.g. just showing the properties, or similar:
originalBean::class.memberProperties
// again just printing them:
.forEach(::println)
You then need to add kotlin-reflect as dependency. You may also want to check the Kotlin reference regarding reflection.

How to create an object in a utility class based on if statement in Java? (Or based on a particular string)

I would have a string that is parsed into an array, as shown here:
class Example extends ParentClass {
private String[] array;
public static Example parseString(String lineToParse) {
array = lineToParse.split("\");
}
public ObjectType1() { // arguments: String, String, String
}
public ObjectType2() { // arguments: String, String, String, double, double
}
}
What I'm wondering is could I do this?
if (array[0].equals("Test")) {
public ObjectType1()
}
Or is there a better way to do this?
I want to create various objects with different arguments each, and the first argument (array[0]) will be applicable to each object, so I was wondering if I could create objects within an if statement like this, or a switch (not sure if that would work either).
I believe a factory method would be useful for you, one that returns instances of classes according to the parameter received:
// ObjectType1, ObjectType2, ObjectType3 inherit from ObjectType
static ObjectType getInstance(String[] array) {
if (array[0].equals("Test"))
return new ObjectType1(array);
else if (array[0].equals("Test2"))
return new ObjectType2(array);
else
return new ObjectType3(array);
}
For the record, actually you can define a class inside a method, this is valid code in Java ... of course, that's hardly a good thing to do:
// ObjectType1, ObjectType2 inherit from ObjectType
public ObjectType example(String[] array) {
if (array[0].equals("Test")) {
class ObjectType1 {
ObjectType1(String[] array) {
}
}
return new ObjectType1(array);
}
else {
class ObjectType2 {
ObjectType2(String[] array) {
}
}
return new ObjectType2(array);
}
}
"Creating" an object means "instantiating it", with new:
ObjectType1 foo = new ObjectType1(...);
You can do that anywhere it's legal to instantiate a class, including in an if statement.
You cannot define classes in arbitrary locations, however.
If you just want to call a method (which should start with a lower-case letter if you want Java developers to understand what you're trying to do), you can call it from anywhere, including inside if statements.
This sounds like you may want to use a [static factory method][1].
[1]: http://en.m.wikipedia.org/wiki/Factory_method_pattern
I guess that you want to dynamically create objects based on a configuration file?
There are lots of ways to achieve this. One simple way is to use reflection to create the objects. Then you do not need any if/switch statements, and if you want to create a new type of object your code does not need to be changed.
Here are some examples for using reflection: Reflection API Code Samples

(no) Properties in Java?

So, I have willfully kept myself a Java n00b until recently, and my first real exposure brought about a minor shock: Java does not have C# style properties!
Ok, I can live with that. However, I can also swear that I have seen property getter/setter code in Java in one codebase, but I cannot remember where. How was that achieved? Is there a language extension for that? Is it related to NetBeans or something?
There is a "standard" pattern for getters and setters in Java, called Bean properties. Basically any method starting with get, taking no arguments and returning a value, is a property getter for a property named as the rest of the method name (with a lowercased start letter). Likewise set creates a setter of a void method with a single argument.
For example:
// Getter for "awesomeString"
public String getAwesomeString() {
return awesomeString;
}
// Setter for "awesomeString"
public void setAwesomeString( String awesomeString ) {
this.awesomeString = awesomeString;
}
Most Java IDEs will generate these methods for you if you ask them (in Eclipse it's as simple as moving the cursor to a field and hitting Ctrl-1, then selecting the option from the list).
For what it's worth, for readability you can actually use is and has in place of get for boolean-type properties too, as in:
public boolean isAwesome();
public boolean hasAwesomeStuff();
I am surprised that no one mentioned project lombok
Yes, currently there are no properties in java. There are some other missing features as well.
But luckily we have project lombok that is trying to improve the situation. It is also getting more and more popular every day.
So, if you're using lombok:
#Getter #Setter int awesomeInteger = 5;
This code is going to generate getAwesomeInteger and setAwesomeInteger as well. So it is quite similar to C# auto-implemented properties.
You can get more info about lombok getters and setters here.
You should definitely check out other features as well.
My favorites are:
val
NoArgsConstructor, RequiredArgsConstructor, AllArgsConstructor
Logs!
Lombok is well-integrated with IDEs, so it is going to show generated methods like if they existed (suggestions, class contents, go to declaration and refactoring).
The only problem with lombok is that other programmers might not know about it. You can always delombok the code but that is rather a workaround than a solution.
"Java Property Support" was proposed for Java 7, but did not make it into the language.
See http://tech.puredanger.com/java7#property for more links and info, if interested.
The bean convention is to write code like this:
private int foo;
public int getFoo() {
return foo;
}
public void setFoo(int newFoo) {
foo = newFoo;
}
In some of the other languages on the JVM, e.g., Groovy, you get overridable properties similar to C#, e.g.,
int foo
which is accessed with a simple .foo and leverages default getFoo and setFoo implementations that you can override as necessary.
public class Animal {
#Getter #Setter private String name;
#Getter #Setter private String gender;
#Getter #Setter private String species;
}
This is something like C# properties. It's http://projectlombok.org/
You may not need for "get" and "set" prefixes, to make it look more like properties, you may do it like this:
public class Person {
private String firstName = "";
private Integer age = 0;
public String firstName() { return firstName; } // getter
public void firstName(String val) { firstName = val; } // setter
public Integer age() { return age; } // getter
public void age(Integer val) { age = val; } //setter
public static void main(String[] args) {
Person p = new Person();
//set
p.firstName("Lemuel");
p.age(40);
//get
System.out.println(String.format("I'm %s, %d yearsold",
p.firstName(),
p.age());
}
}
Most IDEs for Java will automatically generate getter and setter code for you if you want them to. There are a number of different conventions, and an IDE like Eclipse will allow you to choose which one you want to use, and even let you define your own.
Eclipse even includes automated refactoring that will allow you to wrap a property up in a getter and setter and it will modify all the code that accesses the property directly, to make it use the getter and/or setter.
Of course, Eclipse can only modify code that it knows about - any external dependencies you have could be broken by such a refactoring.
My Java experience is not that high either, so anyone feel free to correct me. But AFAIK, the general convention is to write two methods like so:
public string getMyString() {
// return it here
}
public void setMyString(string myString) {
// set it here
}
From Jeffrey Richter's book CLR via C#: (I think these might be the reasons why properties are still not added in JAVA)
A property method may throw an exception; field access never throws an exception.
A property cannot be passed as an out or ref parameter to a method; a field can.
A property method can take a long time to execute; field access always completes
immediately. A common reason to use properties is to perform thread synchronization,
which can stop the thread forever, and therefore, a property should not be
used if thread synchronization is required. In that situation, a method is preferred.
Also, if your class can be accessed remotely (for example, your class is derived from
System.MarshalByRefObject), calling the property method will be very slow, and
therefore, a method is preferred to a property. In my opinion, classes derived from
MarshalByRefObject should never use properties.
If called multiple times in a row, a property method may return a different value each
time; a field returns the same value each time. The System.DateTime class has a readonly
Now property that returns the current date and time. Each time you query this
property, it will return a different value. This is a mistake, and Microsoft wishes that
they could fix the class by making Now a method instead of a property. Environment’s
TickCount property is another example of this mistake.
A property method may cause observable side effects; field access never does. In other
words, a user of a type should be able to set various properties defined by a type in
any order he or she chooses without noticing any different behavior in the type.
A property method may require additional memory or return a reference to something
that is not actually part of the object’s state, so modifying the returned object has no
effect on the original object; querying a field always returns a reference to an object
that is guaranteed to be part of the original object’s state. Working with a property
that returns a copy can be very confusing to developers, and this characteristic is frequently
not documented.
If you're using eclipse then it has the capabilities to auto generate the getter and setter method for the internal attributes, it can be a usefull and timesaving tool.
I'm just releasing Java 5/6 annotations and an annotation processor to help this.
Check out http://code.google.com/p/javadude/wiki/Annotations
The documentation is a bit light right now, but the quickref should get the idea across.
Basically it generates a superclass with the getters/setters (and many other code generation options).
A sample class might look like
#Bean(properties = {
#Property(name="name", bound=true),
#Property(name="age,type=int.class)
})
public class Person extends PersonGen {
}
There are many more samples available, and there are no runtime dependencies in the generated code.
Send me an email if you try it out and find it useful!
-- Scott
There is no property keyword in java (like you could find it in C#) the nearest way to have 1 word getter/setter is to do like in C++:
public class MyClass
{
private int aMyAttribute;
public MyClass()
{
this.aMyAttribute = 0;
}
public void mMyAttribute(int pMyAttributeParameter)
{
this.aMyAttribute = pMyAttributeParameter;
}
public int mMyAttribute()
{
return this.aMyAttribute;
}
}
//usage :
int vIndex = 1;
MyClass vClass = new MyClass();
vClass.mMyAttribute(vIndex);
vIndex = 0;
vIndex = vClass.mMyAttribute();
// vIndex == 1
As previously mentioned for eclipse, integrated development environment (IDE) often can create accessor methods automatically.
You can also do it using NetBeans.
To create accessor methods for your class, open a class file, then Right-click anywhere in the source code editor and choose the menu command Refactor, Encapsulate Fields.
A dialog opens. Click Select All, then click Refactor.
Voilà,
Good luck,
For me the problem is two fold:
All these extra methods {get*/set*} cluttering up the class code.
NOT being able to treat them like properties:
public class Test {
private String _testField;
public String testProperty {
get {
return _testField;
}
set {
_testField = value;
}
}
}
public class TestUser {
private Test test;
public TestUser() {
test = new Test();
test.testProperty = "Just something to store";
System.out.printLn(test.testProperty);
}
}
This is the sort of easy assignment I would like to get back to using. NOT having to use 'method' calling syntax. Can anyone provide some answers as to what happened to Java?
I think that the issue is also about the unnecessary clutter in the code, and not the 'difficulty' of creating the setters/getters. I consider them as ugly-code. I like what C# has. I don't understand the resistance to adding that capability to Java.
My current solution is to use 'public' members when protection is not required:
public class IntReturn {
public int val;
}
public class StringReturn {
public String val;
}
These would be used to return value from say a Lambda:
StringReturn sRtn = new StringReturn()
if(add(2, 3, sRtn)){
System.out.println("Value greater than zero");
}
public boolean add(final int a, final int b, final StringReturn sRtn){
int rtn = a + b;
sRtn.val = "" + rtn;
return rtn > 0; // Just something to use the return for.
}
I also really don't like using a method call to set or get an internal value from a class.
If your information is being transferred as 'immutable', then the new Java record could be a solution. However, it still uses the setter/getter methodology, just without the set/get prefixes.

Categories