簡體   English   中英

在Java中,究竟什么構成“初始化局部變量”?

[英]In Java, what exactly constitutes as “initializing a local variable”?

說我在本地方法中有一段代碼

int a = 5, b;

然后一些代碼間接初始化B如

if (true) b = 5;  // legal 
if (someBool) b = 10; else b = 7; // legal
if (false) b = 5;  // illegal 

即使B總是被初始化,也是非法的

if (a > 10)
b = 4;
if (a <= 10)
b = 4;

我的問題是,本地變量可以被合法地視為“初始化”的所有具體情況是什么?

如果編譯器可以很容易地推斷出每個可能的代碼路徑將通過已設置值的路徑,則可以認為局部變量是“初始化的”。

  • if(true)可以確定總是運行。
  • if(false)可以確定永不運行。
  • if/else可以確定運行至少一個分支,因此如果要保證初始化,必須在每個分支中分配變量。 同樣的原則適用於if/else if/.../else
  • switch語句將運行其中一個可能的case ,或者將命中default情況,因此如果你在所有這些地方分配變量,那么可以保證初始化。

在進行此確定時,Java編譯器不會在方法的各個點檢查每個變量的所有可能值,因為變量是可變的 -它們可以更改。 但是,如果值可以被認為是常數,那么它可以安全地假設它們不會改變。

例如,編譯器不關心您是否分配變量並且從不在代碼中更改它:

boolean val = true;
if(val) {
     b = 5;
}

調試器和事物使您可以即時更改val的值,因此編譯器不會在此進行任何假設。 但是,如果使val 保持不變 ,通過將其聲明為final並使用常量或字面值初始化它,那么編譯器將把它視為與在代碼中使用常量值完全相同。

final boolean val = true;
if(val) {                 // Same as if you'd said `if(true)`
     b = 5;
}

這些常量也可以鏈接,編譯器會將它們簡化為常量值,而不是維護較長的表達式和運算符:

final int five = 5;
final int four = five - 1; // Same as `four = 5 - 1`, or `four = 4`
final boolean val = five > four;
if(val) {           // Same as `if(5 > 4)`, or `if(true)`
     b = 5;
}

有關進一步閱讀,請查看Java規范 (給Radiodef尋找合適的部分的帽子提示。)

在這種情況下:

if (false) b = 5;  // illegal

編譯器拋出異常,因為if(false)可以在編譯時擦除。 即使分析一個不會被任何意思執行的代碼塊也是徒勞的。

在這種情況下:

int a = 5, b;
if (a > 10)
b = 4;
if (a <= 10)
b = 4;

編譯器不能保證該件的代碼將被執行,因為a可以改變其值。 在這種情況下,您可以通過將a標記為final並為其指定一個文字int值(編譯器可以理解)來修復它:

final int a = 5;
int b;
if (a > 10)
    b = 4;
if (a <= 10)
    b = 4;

但請注意,您仍然可以通過給final int a編譯器無法確定的值來破壞此代碼:

final int a = foo();
int b;
if (a > 10)
    b = 4;
if (a <= 10)
    b = 4;

//...

int foo() {
    return 5;
}

更多信息:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM