Rich
Rich

Reputation: 15767

Ensuring a val is initialised in 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?

Upvotes: 4

Views: 302

Answers (1)

miensol
miensol

Reputation: 41638

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.

Upvotes: 12

Related Questions