簡體   English   中英

行為差異:'null'初始化最終靜態成員,'null'初始化最終局部變量

[英]Behaviour Difference: 'null' initialized final static member, and 'null' initialized final local variable

在后續代碼中,我遇到了一個我之前不知道的行為。

考慮一種情況:

public static void main(String[] args) {    
    final String str = null;
    System.out.println(str.length());  // Compiler Warning: NullPointerAccess
}

正如預期的那樣,編譯器在strnull時顯示以下警告 - 空指針訪問:變量str在此位置只能為null。

現在,當我將該變量移動一個初始化為null靜態final字段時

class Demo {
    static final String str = null;

    public static void main(String[] args) {
        System.out.println(str.length());  // No Compiler Warning
    }
}

現在,編譯器沒有顯示任何警告。 AFAIK,編譯器應該知道str是最終的,不會在代碼的任何一點改變它的值。 並且假設它為null ,肯定會在以后導致NullPointerException ,它會這樣做。

雖然編譯器在第一種情況下成功警告我,為什么它在第二種情況下無法識別。 為什么這種行為改變? 如果我將static字段更改為instance字段,並使用Demo實例訪問它,則行為相同。

我認為這種行為可能已在JLS中指定,因此我瀏覽了主題定義分配 ,但沒有找到與此問題相關的任何內容。 任何人都可以解釋行為的變化嗎? 如果可能的話,我正在尋找一些與JLS有關聯的強點嗎?

除此之外,為什么編譯器首先只向我顯示警告 ,因為我認為出於與上述相同的原因,方法調用肯定會在運行時拋出NPE ,因為字段無法更改? 為什么不向我顯示編譯器錯誤? 我是否期望編譯器太多,因為似乎很明顯, str.length()的運行時結果不能比NPE


很抱歉錯過了之前:

我正在使用Eclipse Juno ,在Ubuntu 12.04上使用OpenJDK 7

我不確定在100%,但在第二種情況下,你有最終字段對抗局部變量,有可能為這個最終字段分配一些直接在靜態的值(或實例塊取決於變量是否為靜態)初始化塊:

class Demo {
...
static {
 str = "some text";
}
...
}

所以編譯器不會給你警告。

哇! 原來,這是日食的具體問題。 當我使用以下代碼編譯代碼時:

javac -Xlint:all Demo.java

它沒有對任何案件發出任何警告。 所以,我回到eclipse檢查為這種情況啟用的任何設置,並找到了一個。

Windows - > 首選項 - > Java - > 編譯器 - > 錯誤/警告中 ,在Null Analysis下 ,我可以更改Eclipse編譯器應該處理Null指針訪問的方式。 我可以將其設置為 - 忽略錯誤警告

現在看來這是一個完全愚蠢的問題。 對我感到羞恥。 :(

public static void main(String[] args) {    
    final String str = null;
    System.out.println(str.length());  // Compiler Warning: NullPointerAccess
}

在這種情況下,str是一個局部變量,如果在初始化之前嘗試對其執行任何操作,編譯器將無法編譯。 流分析完全不同,它將檢查代碼的流程,在代碼流中,它檢測到在執行length()操作時,局部變量str只能為null。

class Demo {
    static final String str = null;

    public static void main(String[] args) {
        System.out.println(str.length());  // No Compiler Warning
    }
}

在這種情況下,str是一個實例變量,即使您沒有明確指定,它也將為null。

為什么還沒有警告?

您可以在構造函數中初始化實例變量。 或者你可以在調用lenght()操作之前調用setter方法。 因此它逃脫了流分析(編譯器不確定實例變量在該點是否為空,但在第一種情況下編譯確保局部變量將始終為null)。

暫無
暫無

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

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