Kotlin - attribute visibility to companion object - java

So I have the code below, written in Kotlin.
I'm getting a compilation error on the last instruction line (return params.keys.containsAll(MANDATORY_PARAMS)), the compiler says Unsolved reference: MANDATORY_PARAMS, but I don't really get why.
I thought companion objects were supposed to have some kind of visibility into the attributes of the classes they "keep company to".
What could I do to solve this? How could I make MANDATORY_PARAMS visible to both MandatoryParametersValidator and its companion object?
(disclaimer: this code is being migrated from Java to Kotlin. On Java version, mandatoryParametersHaveBeenProvided used to be a static method on the same class.)
import javax.validation.ConstraintValidator
import javax.validation.ConstraintValidatorContext
class MandatoryParametersValidator : ConstraintValidator<EnforceMandatoryParameters, Map<String, String>> {
val MANDATORY_PARAMS = arrayOf("bookingReference", "lastName")
override fun initialize(constraintAnnotation: EnforceMandatoryParameters?) {
// do nothing
}
override fun isValid(params: Map<String, String>, context: ConstraintValidatorContext?): Boolean {
MANDATORY_PARAMS
.filter { !params.containsKey(it) }
.forEach { parameterName ->
context?.disableDefaultConstraintViolation()
context?.buildConstraintViolationWithTemplate("Mandatory parameter $parameterName is missing.")?.addConstraintViolation()
}
return mandatoryParametersHaveBeenProvided(params)
}
companion object {
fun mandatoryParametersHaveBeenProvided(params: Map<String, String>) : Boolean {
return params.keys.containsAll(MANDATORY_PARAMS)
}
}
}
Thanks a lot!

You need to do two things to get this working
Move MANDATORY_PARAMS into the companion object. The companion object is like the static parts of the class in Java. And MANDATORY_PARAMS would be static final in Java.
Change the type of MANDATORY_PARAMS from Array<String> to List<String> (since containsAll requires a Collection.)
The fixed code looks like this.
...
companion object {
val MANDATORY_PARAMS = listOf("bookingReference", "lastName")
fun mandatoryParametersHaveBeenProvided(params: Map<String, String>) : Boolean {
return params.keys.containsAll(MANDATORY_PARAMS)
}
}
}

MANDATORY_PARAMS is an instance property in this case. Every instance of MandatoryParametersValidator will have its own MANDATORY_PARAMS property, even though it will always be the same value.
Companion objects, on the other hand, are singletons (just like every other object), and they aren't tied to any specific instance of MandatoryParametersValidator. So to access that property, you either need to pass an instance of the class to the function inside the companion object and read the property that it has, or put your property inside the companion object.
This is just like the way that you can't access instance fields and methods from a static function in Java. What you have now is roughly equivalent to this Java code:
class MandatoryParametersValidator {
String[] MANDATORY_PARAMS = ...;
static bool mandatoryParametersHaveBeenProvided(Map<String, String> params) {
...
}
}

Related

How to serialise/deserialise an object in Scala?

I am new to Scala/Java, and I need to see (and then maybe modify as per required) the transport options of default BQ instance
This is the code so far which seems to be printing the object pointer, instead of the value.
transportOptions is of class "TransportOptions" which extends "Serializable"
val bqservice = BigQueryOptions.getDefaultInstance
val transportOptions = bqservice.getTransportOptions
println(transportOptions)
Output :
com.google.cloud.spark.bigquery.repackaged.com.google.cloud.http.HttpTransportOptions#d3e83eb0
How to check the values inside this object? Thanks!
In your example TransportOptions is an interface and the following class HttpTransportOptions implements this interface :
public class HttpTransportOptions implements TransportOptions {
private static final long serialVersionUID = 7890117765045419810L;
private final int connectTimeout;
private final int readTimeout;
private final String httpTransportFactoryClassName;
private transient HttpTransportFactory httpTransportFactory;
For example, you can write an unit test and check the values inside with a breakpoint in your code, example with IntelliJ Idea and Kotlin (the principle is the same with Java and Scala) :
#Test
fun yourTest() {
val bqservice = BigQueryOptions.getDefaultInstance()
val transportOptions = bqservice.transportOptions
println(transportOptions)
}
This is the code so far which seems to be printing the object pointer, instead of the value.
In Scala (like Java) there are no pointers (unless you're using Scala Native), just values of reference types are the references.
Is Java "pass-by-reference" or "pass-by-value"?
The println output means that .toString wasn't overridden and produces class name and instance hash code.
transportOptions has type com.google.cloud.TransportOptions. It is an interface and is implemented by class com.google.cloud.http.HttpTransportOptions.
For example you can find out field values with reflection
// val bqservice = BigQueryOptions.getDefaultInstance
val bqservice = BigQueryOptions.newBuilder()
.setProjectId("XXX") // (*)
.build
val transportOptions = bqservice.getTransportOptions
classOf[TransportOptions].getFields
.foreach(println)
classOf[TransportOptions].getDeclaredFields
.foreach(println)
classOf[HttpTransportOptions].getFields
.map(field => field.getName -> field.get(transportOptions))
.foreach(println)
classOf[HttpTransportOptions].getDeclaredFields
.map(field => {
field.setAccessible(true)
field.getName -> field.get(transportOptions)
})
.foreach(println)
//(serialVersionUID,7890117765045419810)
//(connectTimeout,-1)
//(readTimeout,-1)
//(httpTransportFactoryClassName,com.google.cloud.http.HttpTransportOptions$DefaultHttpTransportFactory)
//(httpTransportFactory,com.google.cloud.http.HttpTransportOptions$DefaultHttpTransportFactory#6e0dec4a)
You can repeat with httpTransportFactory.
getFields returns fields of current class and its parents but only public ones, getDeclaredFields returns fields of only current class but both public and private.
(*) How to fix error: A project ID is required for this service but could not be determined

Reference field in the Interface subclass (Kotlin)

Is there a possible way to reference interface's static field in the class, which implements interface without importing, or calling referencing to interface explicitly.
I want to do like this:
interface Globals {
companion object {
val mc get() = Bloomware.mc
val cPlayer get() = mc.player!!
val cWorld get() = mc.world!!
fun sendPacket(p: Packet<*>?) {
mc.networkHandler!!.sendPacket(p)
}
}
}
(Class user)
object ResourceCancel : Module(), Globals {
#Subscribe
private fun onPacketSend(event: EventPacket.Send) {
cPlayer.jump() // call this
}
I know it's possible in Java, but i can't repeat the same in Kotlin
I'm pretty sure there's no way to do this in Kotlin.
The closest I think you could get is to define your global stuff at the top level in its own package, and then import that package.* in files where you want to access them.
package com.foo.globals
val mc get() = Bloomware.mc
val cPlayer get() = mc.player!!
val cWorld get() = mc.world!!
fun sendPacket(p: Packet<*>?) {
mc.networkHandler!!.sendPacket(p)
}
import com.foo.globals.*
object ResourceCancel : Module() {
#Subscribe
private fun onPacketSend(event: EventPacket.Send) {
cPlayer.jump() // call this
}

How to instantiate a parameterized type class by name [duplicate]

This question already has answers here:
Reflection for Class of generic parameter in Java?
(6 answers)
Closed 4 years ago.
Following Example:
I have a service that can 'start' any vehicle
interface VehicleStarterService<T: Vehicle> {
fun <T : Vehicle> start(vehicle: Class<T>): String {
return vehicle.start
}
}
I would like to start a vehicle type by name like "Car", which would require me to create a VehicleStarterService; however I cannot seem to find a way to instantiate an interface with a class that is instantiated by name.
I would like to do something like (but cannot):
val cls = "Car"
val kClass = Class.forName(cls).kotlin
val service = VehicleStarterService<kClass>()
service.start
I end up having to do the following (creating a service for every paramaterized type I need):
class CarStarterService : VehicleStarterService<Car> {
fun <T> execute() : String {
return start(User::class.java)
}
}
Is there any way to instantiate a paramaterized class in this way?
It's not clear if this would be sufficient for your situation, but perhaps you could just match the class based on the string like this
val cls = "Car"
val service: VehicleStarterService<out Vehicle>? = when (cls) {
"Car" -> object : VehicleStarterService<Car> {}
"Boat" -> object : VehicleStarterService<Boat> {}
"Plane" -> object : VehicleStarterService<Plane> {}
else -> null
}
service?.start(...
EDIT: hashmap registry idea to allow some extensibility..
val serviceRegistry = HashMap<String, VehicleStarterService<out Vehicle>>()
.apply {
//default services
this["Car"] = object : VehicleStarterService<Car> {}
this["Boat"] = object: VehicleStarterService<Boat> {}
}
.
.
.
//Adding entry
serviceRegistry["Plane"] = object: VehicleStarterService<Plane> {}
.
.
.
//Fetching entry
val cls = "Car"
val service = serviceRegistry[cls]
service?.start(...
I don't really see your problem. Note that the generic type information is erased at runtime (at least for the JVM-variant which you are obviously using). So it basically doesn't matter which generically typed service you use.
You can also just use VehicleStarterService<Vehicle> and it will start all your vehicles. If for any reason you need to call a specific (other!) function you still need to check/cast to your actual type... So I see no benefit in trying to get that generic typed interface.
Having said that there are still methods to do it... (note again: it doesn't really matter... generic type information is erased at runtime...)
Now for my tests I use this entry method:
fun startAllTheVehicles(vararg vehicleTypes: String) {
startAllTheVehicles(*vehicleTypes.map { Class.forName(it) }
.map { it as Class<out Vehicle> }
.toTypedArray())
}
Note that it as Class<out Vehicle> is NOT ensuring that you have a class of type Vehicle. It just makes sure that your code compiles when trying to call your functions that declare Class<out Vehicle> as a parameter type.
So starting from there you could use one of the following ways to have an actual generic type available. I am assuming you use something like newInstance within your start service.
Sample with the generic type omitted on the interface (that case is rather easy):
interface VehicleStarterService {
fun <T: Vehicle> start(vehicleType: Class<T>) = vehicleType.newInstance().start
}
Sample method that is called by the above entry function using one service to start all vehicles:
fun <T : Vehicle> startAllTheVehicles(vararg vehicleTypes: Class<out T>) {
val service = object : VehicleStarterService {}
vehicleTypes.forEach { service.start(it) }
}
Still using an interface with generic type (note the changes regarding out T, etc.):
interface VehicleStarterService<T: Vehicle> {
fun start(vehicleType: Class<out T>) = vehicleType.newInstance().start
}
Sample method that is called by the entry function using one service to start all vehicles:
fun <T : Vehicle> startAllTheVehicles(vararg vehicleTypes: Class<out T>) {
// actually it doesn't really matter which type we use...
val service = object : VehicleStarterService<Vehicle> {} // you could even use T instead of Vehicle
vehicleTypes.forEach { service.start(it) }
}
Testing both with the following works as expected:
startAllTheVehicles("Car", "Truck")
Calling it with a type that is actually no Vehicle will give you a ClassCastException at the interface's start-function.

Kotlin: Java can't resolve Kotlin Symbol?

I have a Kotlin Code just like the below, SingleKotlin.instance can be called by the other Kotlin files
class SingleKotlin private constructor(){
companion object {
val instance by lazy {
SingleKotlin()
}
}
}
However, when I try to call SingleKotlin.instance from java, it shows can't resolve symbol 'instance'
I don't understand why, anybody can explian and how can I solve this problem?
Just add #JvmStatic annotation above field (as said in this documentation https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#static-fields)
So, your code should be like this:
class SingleKotlin private constructor(){
companion object {
#JvmStatic
val instance by lazy {
SingleKotlin()
}
}
}
And now you can call it like
SingleKotlin.instance
In addition to #YuriiKyrylchuk's answer: another option (and the only option if you don't have control over the Kotlin code) is to refer to MyClass.Companion from Java. Example:
class MyClass {
companion object {
val x: Int = 0
}
}
And in Java:
MyClass.Companion.getX();
If your SingleKotlin object has a single private constructor without parameters, you can use object instead:
object SingleKotlin {
// some members of SingleKotlin
val x = 42
}
Then in Java you reference it through the INSTANCE static field:
SingleKotlin single = SingleKotlin.INSTANCE;
// or
SingleKotlin.INSTANCE.getX();
You need to call the method from Java like this:
AppUIUtils.Companion.yourMethod()
In additional to Ilya answer you can use #JvmStatic annotation
object SingleKotlin {
// some members of SingleKotlin
#JvmStatic val x = 42
}
Then in Java
SingleKotlin.getX();

What is the equivalent of Java static methods in Kotlin?

There is no static keyword in Kotlin.
What is the best way to represent a static Java method in Kotlin?
You place the function in the "companion object".
So the java code like this:
class Foo {
public static int a() { return 1; }
}
will become
class Foo {
companion object {
fun a() : Int = 1
}
}
You can then use it from inside Kotlin code as
Foo.a();
But from within Java code, you would need to call it as
Foo.Companion.a();
(Which also works from within Kotlin.)
If you don't like having to specify the Companion bit you can either add a #JvmStatic annotation or name your companion class.
From the docs:
Companion Objects
An object declaration inside a class can be marked with the companion
keyword:
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
Members of the companion object can be called by using simply the class
name as the qualifier:
val instance = MyClass.create()
...
However, on the JVM you can have members of companion objects generated
as real static methods and fields, if you use the #JvmStatic
annotation. See the Java interoperability section for more details.
Adding the #JvmStatic annotation looks like this
class Foo {
companion object {
#JvmStatic
fun a() : Int = 1;
}
}
and then it will exist as a real Java static function, accessible from
both Java and Kotlin as Foo.a().
If it is just disliked for the Companion name, then you can also
provide an explicit name for the companion object looks like this:
class Foo {
companion object Blah {
fun a() : Int = 1;
}
}
which will let you call it from Kotlin in the same way, but
from java like Foo.Blah.a() (which will also work in Kotlin).
Docs recommends to solve most of the needs for static functions with package-level functions. They are simply declared outside a class in a source code file. The package of a file can be specified at the beginning of a file with the package keyword.
Declaration
package foo
fun bar() = {}
Usage
import foo.bar
Alternatively
import foo.*
You can now call the function with:
bar()
or if you do not use the import keyword:
foo.bar()
If you do not specify the package the function will be accessible from the root.
If you only have experience with java, this might seem a little strange. The reason is that kotlin is not a strictly object-oriented language. You could say it supports methods outside of classes.
Edit:
They have edited the documentation to no longer include the sentence about recommending package level functions. This is the original that was referred to above.
A. Old Java Way :
Declare a companion object to enclose a static method / variable
class Foo{
companion object {
fun foo() = println("Foo")
val bar ="bar"
}
}
Use :
Foo.foo() // Outputs Foo
println(Foo.bar) // Outputs bar
B. New Kotlin way
Declare directly on file without class on a .kt file.
fun foo() = println("Foo")
val bar ="bar"
Use the methods/variables with their names. (After importing them)
Use :
foo() // Outputs Foo
println(bar) // Outputs bar
Use object to represent val/var/method to make static. You can use object instead of singleton class also. You can use companion if you wanted to make static inside of a class
object Abc{
fun sum(a: Int, b: Int): Int = a + b
}
If you need to call it from Java:
int z = Abc.INSTANCE.sum(x,y);
In Kotlin, ignore INSTANCE.
This also worked for me
object Bell {
#JvmStatic
fun ring() { }
}
from Kotlin
Bell.ring()
from Java
Bell.ring()
Even though this is a bit over 2 years old now, and had plenty of great answers, I am seeing some other ways of getting "static" Kotlin fields are missing. Here is an example guide for Kotlin-Java static interop:
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);
}
}
Michael Anderson's 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
#file:JvmName("KotlinClass")
//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);
}
}
object objectName {
fun funName() {
}
}
Kotlin has no any static keyword. You can use below code for Java and Kotlin
object AppHelper {
#JvmStatic
fun getAge() : Int = 30
}
Call for Java Class
AppHelper.getAge();
Call for Kotlin Class
AppHelper.getAge()
Its work perfectly for me. Thanks
Top-level / companion object for static properties
Top-level
When the properties are somewhat related to a class, define them as top-level properties just before the class declaration:
const val MAX_ATTEMPTS = 3
private const val DEFAULT_NAME = "Guest"
private const val MIN_AGE = 16
data class User(val id: String, val name: String = DEFAULT_NAME)
This is similar to the static properties in Java.
When the properties are completely independent of any class, you can define them as top-level in a separate file without the class.
companion object
When the properties are closely related to a class and will be used only in that class, define them inside a companion object:
data class User(val id: String, val name: String = DEFAULT_NAME) {
companion object {
const val DEFAULT_NAME = "Guest"
const val MIN_AGE = 16
}
}
Top-level / companion object for static methods
Top-level
Similar to the properties above, when the functions are somewhat related to a class, define them just above the class:
fun getAllUsers() { }
fun getProfileFor(userId: String) { }
data class User(val id: String, val name: String)
Usage:
val userList = getAllUsers()
companion object
When the functions are closely related to a class, define them inside a companion object:
data class User(val id: String, val name: String) {
companion object {
fun getAll() { }
fun profileFor(userId: String) { }
}
}
Usage:
val userProfile = User.profileFor("34")
This is similar to the static methods in Java.
The top-level functions are often more idiomatic to Kotlin. A better reason to define functions inside the companion object is when you are extending a companion object with an interface. An example of this is shown in the singleton section.
Nested class for static class
When the classes with related functionalities belong together, they can be grouped together by nesting:
class User(val id: String, val name: String) {
class UserAccess : UserDao {
override fun add(user: User) { }
override fun remove(id: String) { }
}
}
This is equivalent to the static nested classes in Java. The UserAccess class here implements an interface UserDao.
Usage:
fun main() {
val john = User("34", "John")
val userAccess = User.UserAccess()
userAccess.add(john)
}
Singleton object for static INSTANCE
Top-level
When you just want a single object of a class, you no longer need to create a static INSTANCE inside a class like in Java. Simply use a top-level object declaration:
object UserAccess : UserDao {
override fun add(user: User) { }
override fun remove(id: String) { }
}
Notice also how easy it is to extend an interface or a class in a singleton.
The code above, under the hood, produces the following static INSTANCE singleton pattern in Java (simplified):
public final class UserAccess implements UserDao {
public static final UserAccess INSTANCE;
public void add(User user) { }
public void remove(String id) { }
private UserAccess() { }
static { INSTANCE = new UserAccess();}
}
companion object
When the singleton is closely related to a class use companion object:
data class User(val id: String, val name: String) {
companion object : UserDao {
override fun add(user: User) { }
override fun remove(id: String) { }
}
}
This way you get more elegant naming: User.add(john). Also, you make the intent clear that this singleton is only used as a utility for the User class. You can also use the object without the companion keyword inside the class, if you want multiple singletons or groups of functions/properties.
companion object for static factory
Factory functions in Koltin are created using the companion object. Factory functions are useful when you want to provide multiple ways to create an object where the object construction process is complex or when multiple constructors are not expressive enough.
For example, the newInstance() factory function in the following snippet creates a user by generating the id automatically:
class User private constructor(val id: Long, val name: String) {
companion object {
private var currentId = 0L;
fun newInstance(name: String) = User(currentId++, name)
}
}
This is equivalent to the static factory methods in Java.
The constructor is kept private but the companion object has access to the constructor.
In the code above, consistency of the next id generation is guaranteed because a companion object is a singleton, only one object will keep track of the id, there won't be any duplicate ids.
Also notice that companion objects can have properties (currentId in this case) to represent state.
Usage:
val john = User.newInstance("John")
#JvmStatic for Java interoperability
The static concept of Java doesn't exist in Kotlin. A companion object is an instance of a real class called Companion. So, when you call the Kotlin code from Java, an object of the Companion class is first instantiated behind the scenes. You need to call the function using the Companion object in Java:
Profile userProfile = User.Companion.profileFor("34");
For the idiomatic Java naming and less verbosity, use #JvmStatic annotation on that function or property:
companion object {
#JvmStatic
fun profileFor(userId: String): Profile { }
}
The #JvmStatic annotation creates a separate pure static copy of the getProfileFor() function. Now you can use it from Java with regular syntax:
Profile userProfile = User.profileFor("34");
That's it! Hope the examples are useful for your projects.
Simply use this approach
object Foo{
fun foo() = println("Foo")
val bar ="bar"
}
Foo.INSTANCE.foo()
You need to pass companion object for static method because kotlin don’t have static keyword - Members of the companion object can be called by using simply the class name as the qualifier:
package xxx
class ClassName {
companion object {
fun helloWord(str: String): String {
return stringValue
}
}
}
Simply you need to create a companion object and put the function in it
class UtilClass {
companion object {
// #JvmStatic
fun repeatIt5Times(str: String): String = str.repeat(5)
}
}
To invoke the method from a kotlin class:
class KotlinClass{
fun main(args : Array<String>) {
UtilClass.repeatIt5Times("Hello")
}
}
or Using import
import Packagename.UtilClass.Companion.repeatIt5Times
class KotlinClass{
fun main(args : Array<String>) {
repeatIt5Times("Hello")
}
}
To invoke the method from a java class:
class JavaClass{
public static void main(String [] args){
UtilClass.Companion.repeatIt5Times("Hello");
}
}
or by adding #JvmStatic annotation to the method
class JavaClass{
public static void main(String [] args){
UtilClass.repeatIt5Times("Hello")
}
}
or both by adding #JvmStatic annotation to the method and making static import in java
import static Packagename.UtilClass.repeatIt5Times
class JavaClass{
public static void main(String [] args){
repeatIt5Times("Hello")
}
}
There are 2 ways you can apply static in Kotlin
First make a companion object under class
For ex:
class Test{
companion object{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
}
you can call this function as
Test.Companion.isCheck(2)
Another way we can use is to make an object class
object Test{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
Happy Coding!
I would like to add something to above answers.
Yes, you can define functions in source code files(outside class). But it is better if you define static functions inside class using Companion Object because you can add more static functions by leveraging the Kotlin Extensions.
class MyClass {
companion object {
//define static functions here
}
}
//Adding new static function
fun MyClass.Companion.newStaticFunction() {
// ...
}
And you can call above defined function as you will call any function inside Companion Object.
For Java:
public class Constants {
public static final long MAX_CLICK_INTERVAL = 1000;}
Equivalent Kotlin code:
object Constants {
const val MAX_CLICK_INTERVAL: Long = 1000}
So for the equivalent of Java static methods is object class in Kotlin.
To make it short you could use "companion object" to get into Kotlin static world like :
companion object {
const val TAG = "tHomeFragment"
fun newInstance() = HomeFragment()
}
and to make a constant field use "const val" as in the code.
but try to avoid the static classes as it is making difficulties in unit testing using Mockito!.
For Android using a string from a single activity to all the necessary activity.
Just like static in java
public final static String TEA_NAME = "TEA_NAME";
Equivalent approach in Kotlin:
class MainActivity : AppCompatActivity() {
companion object {
const val TEA_NAME = "TEA_NAME"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Another activity where value is needed:
val teaName = MainActivity.TEA_NAME
The exact conversion of the java static method to kotlin equivalent would be like this. e.g. Here the util class has one static method which would be equivalent in both java and kotlin. The use of #JvmStatic is important.
Java code:
class Util{
public static String capitalize(String text){
return text.toUpperCase();}
}
Kotlin code:
class Util {
companion object {
#JvmStatic
fun capitalize(text:String): String {
return text.toUpperCase()
}
}
}
except Michael Anderson's answer, i have coding with other two way in my project.
First:
you can white all variable to one class.
created a kotlin file named Const
object Const {
const val FIRST_NAME_1 = "just"
const val LAST_NAME_1 = "YuMu"
}
You can use it in kotlin and java code
Log.d("stackoverflow", Const.FIRST_NAME_1)
Second:
You can use Kotlin's extension function
created a kotlin file named Ext, below code is the all code in Ext file
package pro.just.yumu
/**
* Created by lpf on 2020-03-18.
*/
const val FIRST_NAME = "just"
const val LAST_NAME = "YuMu"
You can use it in kotlin code
Log.d("stackoverflow", FIRST_NAME)
You can use it in java code
Log.d("stackoverflow", ExtKt.FIRST_NAME);
Write them directly to files.
In Java (ugly):
package xxx;
class XxxUtils {
public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); }
}
In Kotlin:
#file:JvmName("XxxUtils")
package xxx
fun xxx(xxx: Xxx): Yyy = xxx.xxx()
Those two pieces of codes are equaled after compilation (even the compiled file name, the file:JvmName is used to control the compiled file name, which should be put just before the package name declaration).
You can achieve the static functionality in Kotlin by Companion Objects
Adding companion to the object declaration allows for adding the
static functionality to an object even though the actual static
concept does not exist in Kotlin.
A companion object can access all members of the class too, including the private constructors.
A companion object is initialized when the class is instantiated.
A companion object cannot be declared outside the class.
class MyClass{
companion object {
val staticField = "This is an example of static field Object Decleration"
fun getStaticFunction(): String {
return "This is example of static function for Object Decleration"
}
}
}
Members of the companion object can be called by using simply the class name as the qualifier:
Output:
MyClass.staticField // This is an example of static field Object Decleration
MyClass.getStaticFunction() : // This is an example of static function for Object Decleration
Use #JVMStatic Annotation
companion object {
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String, param2: String) =
EditProfileFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
A lot of people mention companion objects, which is correct. But, just so you know, you can also use any sort of object (using the object keyword, not class) i.e.,
object StringUtils {
fun toUpper(s: String) : String { ... }
}
Use it just like any static method in java:
StringUtils.toUpper("foobar")
That sort of pattern is kind of useless in Kotlin though, one of its strengths is that it gets rid of the need for classes filled with static methods. It is more appropriate to utilize global, extension and/or local functions instead, depending on your use case. Where I work we often define global extension functions in a separate, flat file with the naming convention: [className]Extensions.kt i.e., FooExtensions.kt. But more typically we write functions where they are needed inside their operating class or object.
Let, you have a class Student. And you have one static method getUniversityName() & one static field called totalStudent.
You should declare companion object block inside your class.
companion object {
// define static method & field here.
}
Then your class looks like
class Student(var name: String, var city: String, var rollNumber: Double = 0.0) {
// use companion object structure
companion object {
// below method will work as static method
fun getUniversityName(): String = "MBSTU"
// below field will work as static field
var totalStudent = 30
}
}
Then you can use those static method and fields like this way.
println("University : " + Student.getUniversityName() + ", Total Student: " + Student.totalStudent)
// Output:
// University : MBSTU, Total Student: 30
There is no static keyword in kotlin. kotlin docs recommends to use package-level functions if u want to follow DRY.
Create a file with .kt extension and put your method in it.
package p
fun m(){
//fun body
}
after compilation m will have a signature of public static final void
and
import p.m
☺
In Java, we can write in below way
class MyClass {
public static int myMethod() {
return 1;
}
}
In Kotlin, we can write in below way
class MyClass {
companion object {
fun myMethod() : Int = 1
}
}
a companion is used as static in Kotlin.
The kotlin documents provider three ways to do that,
the first is define function in package,without class:
package com.example
fun f() = 1
the second is use #JvmStatic annotation:
package com.example
class A{
#JvmStatic
fun f() = 1
}
and the third is use companion object:
package com.example
clss A{
companion object{
fun f() = 1
}
}
All static member and function should be inside companion block
companion object {
#JvmStatic
fun main(args: Array<String>) {
}
fun staticMethod() {
}
}
If you need a function or a property to be tied to a class rather than to instances of it, you can declare it inside a companion object:
class Car(val horsepowers: Int) {
companion object Factory {
val cars = mutableListOf<Car>()
fun makeCar(horsepowers: Int): Car {
val car = Car(horsepowers)
cars.add(car)
return car
}
}
}
The companion object is a singleton, and its members can be accessed directly via the name of the containing class
val car = Car.makeCar(150)
println(Car.Factory.cars.size)
You can use Companion Objects - kotlinlang
Which it can be shown by first creating that Interface
interface I<T> {
}
Then we have to make a function inside of that interface:
fun SomeFunc(): T
Then after, We need a class:
class SomeClass {}
inside that class we need a companion Object inside that class:
companion object : I<SomeClass> {}
inside that Companion Object we need that old SomeFunc function, But we need to over ride it:
override fun SomeFunc(): SomeClass = SomeClass()
Finally below all of that work, We need something to power that Static function, We need a variable:
var e:I<SomeClass> = SomeClass()

Categories