亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么我們不能通過未初始化的局部變量訪問靜態內容?

為什么我們不能通過未初始化的局部變量訪問靜態內容?

守候你守候我 2023-08-04 14:45:47
看看下面的代碼:class Foo{    public static int x = 1;}class Bar{        public static void main(String[] args) {        Foo foo;        System.out.println(foo.x); // Error: Variable 'foo' might not have been initialized    }}x正如您所看到的,在嘗試通過未初始化的局部變量Foo foo;代碼訪問靜態字段時foo.x會生成編譯錯誤:Variable 'foo' might not have been initialized。這個錯誤看起來似乎是有道理的,但只有當我們意識到要訪問成員時,staticJVM 實際上并不使用變量的值,而只使用其類型。例如,我可以foo使用值進行初始化null,這將使我們可以x毫無問題地訪問:Foo foo = null;System.out.println(foo.x); //compiles and at runtime prints 1!!! 這種情況之所以有效,是因為編譯器意識到它x是靜態的,并把foo.x它當作是這樣寫的Foo.x(至少到目前為止我是這么認為的)。那么為什么編譯器突然堅持使用一個它根本不會使用的foo值呢?免責聲明:這不是在實際應用程序中使用的代碼,而是一個有趣的現象,我在 Stack Overflow 上找不到答案,所以我決定詢問一下。
查看完整描述

4 回答

?
白板的微信

TA貢獻1883條經驗 獲得超3個贊

§15.11。字段訪問表達式

如果該字段是靜態的

對 Primary 表達式進行求值,并丟棄結果。如果主表達式的求值突然完成,則字段訪問表達式也會出于同樣的原因突然完成。

之前它指出字段訪問由 標識?Primary.Identifier。

這表明,即使它似乎沒有使用Primary,它仍然會被評估,然后結果會被丟棄,這就是為什么它需要初始化。當評估如引用中所述停止訪問時,這可能會產生影響。

編輯:

這是一個簡短的示例,只是為了直觀地演示Primary即使結果被丟棄,也會對 進行評估:

class Foo {

? ? public static int x = 1;

? ??

? ? public static Foo dummyFoo() throws InterruptedException {

? ? ? ? Thread.sleep(5000);

? ? ? ? return null;

? ? }

? ??

? ? public static void main(String[] args) throws InterruptedException {

? ? ? ? System.out.println(dummyFoo().x);

? ? ? ? System.out.println(Foo.x);

? ? }

}

在這里您可以看到它dummyFoo()仍然被評估,因為它print被延遲了 5 秒,Thread.sleep()即使它總是返回一個null被丟棄的值。


如果未計算表達式,則會立即出現,這可以在直接使用print類訪問時看到 。FooxFoo.x


注意:?方法調用也被視為§15.8 主表達式Primary中所示。



查看完整回答
反對 回復 2023-08-04
?
米脂

TA貢獻1836條經驗 獲得超3個贊

第 16 章 明確分配

當發生對其值的任何訪問時,每個局部變量(第 14.4 節)和每個空白最終字段(第 4.12.4 節、第 8.3.1.2 節)必須具有明確指定的值。

您嘗試通過局部變量訪問什么并不重要。規則是必須在此之前明確賦值。

要計算字段訪問表達式?foo.x,必須首先計算primary它的部分 ( )。foo這意味著將發生訪問foo,這將導致編譯時錯誤。

對于局部變量或空白最終字段 x 的每次訪問,必須在訪問之前明確分配 x,否則會發生編譯時錯誤。


查看完整回答
反對 回復 2023-08-04
?
慕的地10843

TA貢獻1785條經驗 獲得超8個贊

保持規則盡可能簡單是有價值的,“不要使用可能尚未初始化的變量”就這么簡單。

更重要的是,有一種調用靜態方法的既定方法 - 始終使用類名,而不是變量。

System.out.println(Foo.x);

變量“foo”是不需要的開銷,應該被刪除,編譯器錯誤和警告可以被視為有助于實現這一點。


查看完整回答
反對 回復 2023-08-04
?
SMILET

TA貢獻1796條經驗 獲得超4個贊

其他答案完美地解釋了正在發生的事情背后的機制。也許您還想了解 Java 規范背后的基本原理。作為一個 Java 專家,我無法告訴你最初的原因,但讓我指出這一點:

  • 每一段代碼要么有意義,要么觸發編譯錯誤。

  • (對于靜態,因為實例是不必要的,Foo.x所以很自然。)

  • 現在,我們該怎么辦foo.x(通過實例變量訪問)?

    • 這可能是一個編譯錯誤,如 C# 中的錯誤,或者

    • 它有一個意義。因為Foo.x已經意味著“簡單地訪問”,所以該表達具有不同的含義x是合理的;也就是說,表達式的每個部分都是有效且可訪問的。 foo.xx

希望有知情人士能說出真正的原因。:-)


查看完整回答
反對 回復 2023-08-04
  • 4 回答
  • 0 關注
  • 180 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號