Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ensuring a val is initialised in Kotlin

Tags:

kotlin

I have the following method in Java:

public void doSomething() {
    final boolean promote = false;
    final String bob;

    if (promote) {
        try(StringWriter sw = new StringWriter()) {
            sw.write("this is a test");
            bob = sw.toString();
        } catch (IOException e) {
            e.printStackTrace();
            throw new IllegalStateException();
        }
    } else {
        bob = "anaconda";
    }

    System.out.println(bob);
}

When I convert this to Kotlin:

    val promote = false
    val bob: String

    if (promote) {
        try {
            StringWriter().use { sw ->
                sw.write("this is a test")
                bob = sw.toString()
            }
        } catch (e: IOException) {
            e.printStackTrace()
            throw IllegalStateException()
        }
    } else {
        bob = "anaconda"
    }

    println(bob)

But I get a compiler error on the last line: Variable 'bob' must be initialized.

I can't see how Kotlin could fail to initialise the bob variable when the Java compiler is so sure that the variable has either been initialised or an exception has been thrown.

Is my only option to change bob to a var and initialise it?

like image 561
Rich Avatar asked Dec 15 '22 05:12

Rich


1 Answers

Assign the result of use method to the variable like so:

bob = StringWriter().use { sw ->
    sw.write("this is a test")
    sw.toString()
}

The Java compiler is able to figure out that the variable will be initialised because the try with resources is a language feature. The use method on the other hand is a library feature with behavior dependent on the implementation that is actually imported and used. In other words the Kotlin compiler has no way of knowing if the function passed as an argument to use will be invoked immediately or not.

like image 160
miensol Avatar answered Jan 04 '23 01:01

miensol