139

I want to be able to save a class instance to a private/public static variable, but I can't figure out how to do this in Kotlin.

public class Foo {
    private static Foo instance;

    public Foo() {
        if (instance == null) {
            instance = this;
        }
    }
    
    public static Foo get() {
        return instance;
    }
}
2
  • 3
    If you want to create a singleton, check out kotlinlang.org/docs/reference/…. Commented May 9, 2017 at 13:37
  • @Miha_x64 I'm sure he wants a static class member and not a singleton. Commented Apr 3 at 3:42

4 Answers 4

192

Update: Anyone (like OP) who just needs a so-called "Singleton", sometimes called "Service" (except in Android), should simply use Kotlin's built-in:

object Foo {
    // Done, this already does what OP needed,
    // because the boilerplate codes (like static field and constructor),
    // are taken care of by Kotlin.
}

(Like Roman rightly pointed out in the comment-section.)

Previous answer; If you have (or plan to have) multiple static variables, then continue reading:

The closest thing to Java's static fields is a companion object. You can find the documentation reference for them here: https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects

Your code in Kotlin would look something like this:

class Foo {

    companion object {
        private lateinit var instance: Foo

        fun get(): Foo {
            return instance;
        }
    }

    init {
        if (instance == null) {
            instance = this
        }
    }

}

If you want your fields/methods to be exposed as static to Java callers, you can apply the @JvmStatic annotation:

class Foo {

    companion object {
        private lateinit var instance: Foo

        @JvmStatic fun get(): Foo {
            return instance;
        }
    }

    init {
        if (instance == null) {
            instance = this
        }
    }

}

Note that @JvmStatic does not need any import (as it's built-in feature of Kotlin).

Sign up to request clarification or add additional context in comments.

4 Comments

If you want to use it like a static final field in Java without getters, you probably should mark it @JvmField
@artaxerx Interesting, write this answer u as an answer. I'd like to hear more as I always thought needing a companion object was just ab awful requirement.
@andrew-s no, @JvmField would work as described only within companion object, it just omits getter and setter functions
Here in the example private lateinit var instance: Foo is of not-nullable type, so checking instance == null would never work as expected
73

It looks that you want to define a singleton object. It is supported in Kotlin as a first-class concept:

object Foo {
  ... 
}

All the boilerplate code with static field and constructor is taken care by the Kotlin automatically. You don't have to write any of that.

From the Kotlin code you can refer to the instance of this object simply as Foo. From the Java code you can referer to the instance of this object as Foo.INSTANCE, because the Kotlin compiler automatically creates the corresponding static field named INSTANCE.

3 Comments

This is the much better solution, however, for my use case I needed a class because it needed to be able to be created by a Java class loader.
An object is accessible throughout the entire project though, couldn't that hinder performance?
@ArthurKasparian if you want to prevent access it can be marked private/internal/protected
20

first you create a simple class then after create a block followed by companion object keyword

for example:

class Test{

    companion object{

        fun  getValue(): String{

           return "Test String"

        }
    }
}

you can call this class function using class name dot function name

for example:

// here you will get the function value
Test.getValue() 

Comments

3

You can create a companion object for the class, and if you want the field to be static you can use the annotation @JvmStatic. Companion object have access to private members of the class it is companion for.

See below an example:

class User {
    private lateinit var name: String

    override fun toString() = name

    companion object {
        @JvmStatic
        val instance by lazy {
            User().apply { name = "jtonic" }
        }
    }
}

class CompanionTest {

    @Test
    fun `test companion object`() {
        User.instance.toString() shouldBe "jtonic"
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.