2012-10-17 87 views
5

這被看作是代碼的Java語言中的片段:分支無法通過編譯器

public void name(){ 
int value = 9; 
int o; 
if(value > 9) 
o = 5; 

if(value <= 9) 
o = 8; 

System.out.println(o); 
} 

爲什麼編譯器看不到第二個if語句考慮價值的最後一個選項? 它不會編譯。 最好的問候

+3

錯誤是:變量o可能沒有被初始化(System.out.println(o)) –

+2

爲什麼兩個if語句而不是if..else? – CBredlow

+0

我只是在探索語言。這兩個陳述沒有特別的理由。 – uml

回答

5

編譯器必須把value爲可更改。聲明它finalfixes the problem

public void name(){ 
    final int value = 9; 
    int o; 
    if(value > 9) o = 5; 
    if(value <= 9) o = 8; 
    System.out.println(o); 
} 
+0

我很驚訝它不能輕易推測它在這種情況下是不可變的 –

+1

@BrianAgnew我只能猜測編譯器不允許將兩個'if'中的兩個讀取值視爲訪問相同的價值(並因此使兩個條件互補)。 – dasblinkenlight

+1

編譯器只能在檢查明確賦值時對常量表達式進行操作。 'value> 9'和'value <= 9'都不是常量表達式,除非'value'是常量變量,它本質上是一個'final'變量。 – pingw33n

0

在編譯:

編譯器看到的,你沒有初始化的變量的「o」,你是在系統輸出打印。

你可以做到這一點:除非你說,否則

public void name(){ 
int value = 9; 
int o; 
if(value > 9) 
o = 5; 

else 
o = 8; 

System.out.println(o); 
} 
0

初始化Ø前if語句聲明後

o=0; 
0

按JLS (§16)每一個局部變量和非空字段必須明確賦值纔可以用過的。編譯器通過一些基本的靜態分析來確保它。

明確賦值背後的思想是,對本地變量或空白最終字段的賦值必須發生在訪問的每個可能的執行路徑上。類似地,明確的未分配背後的想法是,在分配的任何可能的執行路徑上,不允許其他分配給空白的最終變量。

靜態分析器只能推導常量表達式的值($15.28)在您的示例中不是這種情況。

1

原始版本無法編譯的原因是JLS section 16中的JLS'「明確分配」規則說o尚未明確分配。編譯器用一個神祕的消息報告這個消息,說「o可能沒有被初始化」。

現在,任何具有簡單演繹技巧的人都會看到第2個if條件是否定第1個條件,因此該變量實際上總是會被初始化。但是,JLS不允許編譯器進行扣除。 JLS說這是一個錯誤...

有很多方法可以解決這個問題。例如

  • 在聲明中指定o
  • 將兩個if語句替換爲單個if/else語句。
  • 聲明valuefinal

上次修復很有趣。它的工作原理是JLS明確的分配規則需要編譯器將編譯時常量布爾值表達式的值考慮在內。

本聲明(與final加)

final int value = 9; 

意味着value是一個編譯時間常數。這意味着value <= 9value > 9也是編譯時常量。因此,JLS明確分配規則指出o之後

if(value <= 9) o = 8; 

明確指定的,可沒有一個編譯錯誤以後使用。


明確賦值規則旨在防止使用未初始化的變量,並防止空白final變量初始化一次以上。

JLS在明確賦值規則中對錶達式值的保守處理旨在避免一個Java編譯器推斷出明確賦值,但另一個不能賦值的問題。編譯時常量表達式的子表達式可以通過簡單地評估表達式來處理,並且JLS規則隱式識別這個表達式。