2014-11-06 43 views
5

的靜態最終場爲實例字段和同名的局部變量,我們可以有資格進入該領域的前綴this.區分在靜態上下文中通過使用類名稱來限制訪問同樣的事情:分配到同一個名字

import java.util.*; 

class Test { 
    public static final Map<String,Object> map; 

    static { 
     Map<String,Object> map = new HashMap<>(); 

     // ... 
     // assume I fill the map with useful data here 
     // ... 

     // now I want to freeze it and assign it to the field 
     Test.map = Collections.unmodifiableMap(map); 
    } 
} 

編譯器不需要這個代碼。我有幾個像這樣的變量,並且對於所有這些變量都會大喊:「無法爲最終變量賦值」。如果我不是分配給它,它抱怨「變量未初始化」,而不是。如果我在開始時分配給靜態字段並嘗試使地圖之後不可修改,則它會抱怨「變量可能已被分配」。這對任何事都不滿意。

這是語言中的缺陷還是編譯器中的錯誤?按照它的說法,壓縮編譯器的最佳方法是什麼?

+1

使用兩個不同的名稱。沒有理由認爲靜態塊內的'map'必須與靜態'map'域具有相同的名稱。 – ajb 2014-11-06 02:53:20

+0

重命名確實有用,但它很醜陋,因爲我在初始化塊中多次使用這些變量,而且它們對於它們的專有名稱會更有意義。我想知道是否有更好的東西。 – Boann 2014-11-06 02:56:25

回答

5

解決最簡單的方法如下:

import java.util.*; 

class Test { 
    public static final Map<String,Object> map; 

    static { 
     Map<String,Object> contents = new HashMap<>(); 

     map = Collections.unmodifiableMap(contents); 
    } 
} 

不知怎的,它似乎是你是否有資格在Java 8類名的常量,編譯器將不擁有它。

更新

一些更多的挖掘後,似乎Java Language Specification明確規定,簡單(非限定)名稱需要用於最終字段(突出礦井)的分配:

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

同樣,每個空白的最終變量最多隻能分配一次; 當它發生分配時,它必須明確地未分配。

這樣的分配被定義爲發生當且僅當任一變量的 簡單名稱(或者,對於一個場,通過該限定其簡單的名稱 )發生在賦值 操作者的左手側

+1

感謝您在JLS中跟蹤此信息。 – ajb 2014-11-06 03:06:47

1

它看起來像它的工作原理說

public static final <something> x; 
static { 
    x = <whatever>; 
} 

但不

public static final <something> x; 
static { 
    MyClass.x = <whatever>; 
} 

我不知道爲什麼,但是這是我得到的行爲。爲了避免出現這種情況,只需將Test.map更改爲map,然後更改其他map變量的名稱。

P.S. Robby的答案解釋了行爲的原因。

0

我意識到一種解決方法,使用一種方法來初始化字段而不是靜態塊。在方法內部,變量當然可以被命名爲任何想要命名的foo:

public static final Map<String,Object> map = initMap(); 

private static Map<String,Object> initMap() { 
    ... 
} 
相關問題