Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 392
Mario Avatar asked Mar 27 '16 10:03

Mario


1 Answers

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()
  }
like image 110
Ilya Ryzhenkov Avatar answered Sep 21 '22 19:09

Ilya Ryzhenkov