Kotlin: "synchronized" makes compiler not to be sure about the initialization of a variable
Asked Answered
P

1

7

Let's imagine the next piece of Kotlin code that performs some query to a database by means a JDBC connector:

    var results : ResultSet
    preparedStatement.clearParameters()
    preparedStatement.setInt(1,value1);
    preparedStatement.setInt(2,value2)
    results = preparedStatement.executeQuery()
    while(results.next()) {
        // parse results
    }

that compiles without problems. However, when I try to add thread safety to the access to the preparedStatement:

    var results : ResultSet
    synchronized(preparedStatement) {
        preparedStatement.clearParameters()
        preparedStatement.setInt(1,value1);
        preparedStatement.setInt(2,value2)
        results = preparedStatement.executeQuery()
    }
    while(results.next()) {
        // parse results
    }

... I got a "Variable 'results' must be initialized". It seems the synchronized block acts as a conditional block, but you can be sure that it will be executed once, before the while block.

I have implemented this same block in Java and I don't get the error. Is this a design/implementation error of Kotlin? Or does it have a good reason to behave like that?

Palmieri answered 27/3, 2016 at 10:51 Comment(0)
D
17

synchronized is just an inline function and compiler doesn't know if lambda will be executed once, or even executed at all. Idiomatic way is to return value from lambda and assign it to the local:

val results =
  synchronized(preparedStatement) {
    preparedStatement.clearParameters()
    preparedStatement.setInt(1,value1);
    preparedStatement.setInt(2,value2)
    preparedStatement.executeQuery()
  }
Daloris answered 27/3, 2016 at 11:3 Comment(1)
@Ilya are there any plans to make the compiler to support such cases? With mustExecute closure specifier or something?Agincourt

© 2022 - 2024 — McMap. All rights reserved.