2016-03-27 11 views
6

Hãy tưởng tượng các mảnh tiếp theo của mã Kotlin rằng thực hiện một số truy vấn đến cơ sở dữ liệu bằng cách có nghĩa là một kết nối JDBC:Kotlin: "đồng bộ" làm cho trình biên dịch không chắc chắn về việc khởi tạo một biến

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

rằng biên dịch không vấn đe. Tuy nhiên, khi tôi cố gắng thêm chủ đề an toàn để truy cập vào các PreparedStatement:

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

... Tôi đã một "Biến 'kết quả' phải được khởi tạo". Dường như khối synchronized đóng vai trò như một khối điều kiện, nhưng bạn có thể chắc chắn rằng nó sẽ được thực hiện một lần, trước khối while.

Tôi đã triển khai cùng một khối này trong Java và tôi không gặp lỗi. Đây có phải là lỗi thiết kế/triển khai của Kotlin không? Hay nó có lý do chính đáng để cư xử như thế?

Trả lời

15

synchronized chỉ là một hàm nội tuyến và trình biên dịch không biết nếu lambda sẽ được thực hiện một lần, hoặc thậm chí được thực hiện ở tất cả. Cách thành ngữ là trả lại giá trị từ lambda và gán giá trị đó cho địa phương:

val results = 
    synchronized(preparedStatement) { 
    preparedStatement.clearParameters() 
    preparedStatement.setInt(1,value1); 
    preparedStatement.setInt(2,value2) 
    preparedStatement.executeQuery() 
    } 
+0

tuyệt vời! cảm ơn nhiều – Mario

+0

@ Ilya có kế hoạch nào để làm cho trình biên dịch hỗ trợ các trường hợp như vậy không? Với 'mustExecute' closure specifier hoặc một cái gì đó? – voddan

Các vấn đề liên quan