2016-06-21 144 views
4
被初始化

我已經在Java中,下面的方法:確保VAL在科特林

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); 
} 

當我將它轉換爲科特林:

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) 

,但我得到的最後一行編譯器錯誤: Variable 'bob' must be initialized.

我看不出Kotlin可能無法初始化bob變量,因爲當Java編譯器確信變量已被初始化或異常已被拋出。

我是唯一選擇將bob更改爲var並初始化它嗎?

回答

12

指定use方法的結果變量,像這樣:

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

Java編譯器能夠找出這個變量將被初始化,因爲try with resources是一種語言功能。另一方面,use方法是一個庫特性,其行爲取決於實際導入和使用的實現。換句話說,Kotlin編譯器無法知道函數是否作爲參數傳遞給use將立即被調用。

+0

好吧,由於使用內聯,編譯器將知道如果傳遞的函數被調用,那會立即發生。 – Rocoty

+1

@Rocoty注意'use'被內聯的事實取決於提供函數的庫(在這種情況下是stdlib)。想象一下這樣的實現: 'inline fun T.use(block:(T) - > R):R? {if(otherFunc()){block(this)}} else {null}'。取決於如果內聯了'otherFunc()',編譯器可以嘗試找出更多的東西,但它很快變得複雜。 – miensol