2011-11-13 70 views
3
public class A{ 
} 

A a = new A(){{ 
    final int x = 1; // IT HAS TO BE FINAL HERE. WHY? 
}}; 

A aa = new A(){ 
    int x = 1; // THIS NEED NOT BE FINAL. WHY? 
    final int y = 1; // STILL FINAL IS ALLOWED HERE. WHY? 
    public int getX(){ 
     return x; 
    } 
}; 

有人可以回答在代碼段中提到的問題嗎?Java中{}和{{}}初始化的區別

由於

回答

3
A a = new A(){{ 
    final int x = 1; // IT HAS TO BE FINAL HERE. WHY? 

It needn't.

兩者之間的區別是,在第一種情況下,你寫的用於初始化每個對象在雙括號中的代碼。那x是它的局部變量(與A類的對象沒有任何關係)。

在第二種情況下,您正在定義類體。 x將是其成員變量。如果它是static,它的類變量。如果final一(基本上)不變。

+0

有沒有解釋Java語言的基本細節的Java書? – user855

+0

@ajay是的,它被稱爲[Java語言規範](http://java.sun.com/docs/books/jls/)。 –

1

第一個實例A a = new A(){{...具有聲明中的初始化塊。編寫它的另一種方式是這樣的:

A a = new A() 
{ 
    { 
     final int x = 1; // This is inside an initialisation block 
    }   
}; 

更改格式使其更加明顯。

+0

爲什麼靜態初始化塊不允許在其中放置static final int x = 1? – user855

+1

第一個實例沒有靜態初始化塊,它有一個實例初始化塊。你可以把東西放在引用實例的塊中(雙引號初始化技巧是如何工作的)。 –

+0

內部{}是一個初始化塊,但不是_static_。如果它是靜態的,它會在它之前有關鍵字'static' - 但是你不能在匿名內部類中使用靜態初始化器。 –

2

我想知道,爲什麼要使用第一版的代碼(帶有{{}}的代碼)。在其中聲明的變量x根本就沒有用處,它只在本地定義它的塊範圍,並且在匿名類中,所以您將無法在代碼中的任何位置引用它。

反正x聲明的第一個版本不必須final,它編譯一樣細,有或沒有final

+1

你會使用雙大括號版本,因爲它是一個成語:http://c2.com/cgi/wiki?DoubleBraceInitialization我個人認爲這不是一個很好的;它掩蓋了驚人的開銷。 –

4

外集{}聲明一個子類匿名

內集聲明子類中的初始化塊。

通過下面的例子,它變得更容易理解這是怎麼回事:

List<String> strings = new ArrayList<String>() {{ 
    add("string"); 
    add("another string"); 
}}; 

你基本上說:我想列出的一個子類,它在初始化時調用方法add

它類似於:

List<String> strings = new ArrayList<String>(); 
strings.add("string"); 
strings.add("another string"); 
+2

內部{}是一個初始化塊,但不是_static_。如果它是靜態的,它會在它之前有關鍵字'static' - 但是你不能在匿名內部類中使用靜態初始化器。 –

+0

的確,我寫得太快了:)編輯出來,謝謝。 – Guillaume

1

在你的第一個例子中的括號內創造一種叫做實例初始化。在構建對象時,初始化變量和調用實例方法是一種難以理解的方式。因此,第一個示例創建了A的匿名子類,並在初始化程序的範圍內創建了一個局部變量。它不一定是最終的。

在第二個示例中,您正在創建A的匿名子類,但未創建實例初始值設定項,您創建的變量是匿名子類的實例變量。

相關問題