2015-06-14 88 views
19

這是如何編譯沒有錯誤?根據我的理解,編譯器檢查變量的類型(在本例中爲String),然後查看右側表達式的類型是否與變量的類型相對應(或者至少是一個子類型,但讓我們堅持簡單的情況,因爲它是最終的,所以String類)。爲什麼變量初始化到賦值表達式[String x =(x = y)]編譯?

public class InitClass { 
    public static void main(String[] args) { 
    String str = (str = "hello"); 
    System.out.println(str); 
    } 
} 

我的問題是如何編譯str = "hello"?編譯器是否已經知道str應該是String

+0

(str =「hello」)返回字符串「hello」。 Eclipse不鼓勵它的消息:「賦值給變量str沒有任何效果」 – LeTex

+3

@LeTex我通常會將Eclipse設置得更嚴格,並將它們報告爲錯誤而不是警告。即使JLS允許任何人使用這些結構,我也沒有理由這樣做。 – biziclop

+2

這是一個有趣的問題,你可能會想「誰在寫這樣的代碼,爲什麼」。純粹學術,當然? – TEK

回答

15

當評估一個assignment expression

首先,左邊的操作數進行評估,以產生可變的。如果 該評估突然完成,則由於同樣的原因,分配表達式 突然完成;右邊的操作數不是 評估和沒有分配發生。

產生變量str。然後

否則,右側的操作數被評估爲。如果此評估 突然完成,則出於同樣的原因,分配表達式突然完成 並且不會發生分配。

在你的例子中,右手操作數本身就是另一個賦值表達式。所以str,賦值運算符的右手操作數,再次被計算爲產生一個變量str。然後

否則,右邊的操作數的值被轉換爲 類型左側的變量,進行值集轉換 (§5.1.13)到相應的標準值集合(而不是 擴展指數值集),和轉換的結果是 存儲到變量中。

因此"hello"被存儲到strAnd since

在運行時,分配表達式的結果是 已經發生的分配後的變量的值。 賦值表達式的結果本身不是一個變量。

"hello"分配給str的結果是值"hello",則該值被再次存儲在str

0

首先發生的事情是,編譯器確定引用的類型,然後知道這是一個字符串爲str分配「hello」是有效的。

5

你的情況下,相當於

String str; 
str = (str = "hello"); 

雖然分配是好笑的看着,有什麼錯概念。

儘管如此,引用自身的變量初始化顯然不是一個好主意。編譯器會嘗試在很可能出現程序錯誤的情況下將其標記出來;編譯器無法做到這一點;並且也可能在其他時間過度。

局部變量比字段變量有更嚴格的要求 - 在使用它的值之前,它必須首先被賦值。例如,這將不會編譯,因爲在分配它之前會讀取本地變量。

String str; // local variable 
str = str; // error, try to read `str` before it's assigned 

一個字段變量總是有一個默認的初始值;儘管如此,編譯器檢查明顯的程序設計師的失誤

int x = x+1; // error. x is field variable. 

但是,如果這樣的檢查失敗這不是災難性的,因爲x有明確的工作前值0

​​

但是,如果xfinal,代碼以上失敗,因爲編譯器需要在讀取x之前先確定分配x,這與局部變量的要求相同。但這種檢查可以被規避,因爲它是不可能的分析和防止它充分爲字段變量

final int x = (this).x+1; // compiles! 

在某些情況下,編譯做得過分,預防涉及拉姆達

Runnable r1 =()->System.out.println(r1); // r1 is a field variable 

沒有什麼合法的使用情況在這個用例中概念上是有問題的;它也可以被(this).規避。

+1

你答案的最後部分非常有趣,+1 – user2336315

相關問題