2013-11-21 57 views
2

我嘗試使用下面的方法來創建List實例:類型差異

List<String> listOne = new ArrayList<String>(); 

List<String> listTwo = new ArrayList<String>(){}; 

List<String> listThree = new ArrayList<String>() {{}}; 

只有listOne作爲java.util.ArrayList初始化,但listTwolistThree都沒有。

在初始化listTwo和listThree時會發生什麼,以及如何更好地理解它?

我的測試示例如下:

import java.util.ArrayList; 
import java.util.List; 

public class Test { 
    public static void main(String[] args) { 

     List<String> listOne = new ArrayList<String>(); 

     List<String> listTwo = new ArrayList<String>(){}; 

     List<String> listThree = new ArrayList<String>() {{}}; 

     System.out.printf("listOne.getClass() == listTwo.getClass() is %b \n", 
       listOne.getClass() == listTwo.getClass()); 

     System.out.printf("listOne.getClass() == listThree.getClass() is %b \n", 
       listOne.getClass() == listThree.getClass()); 

     System.out.printf("listThree.getClass() == listTwo.getClass() is %b \n", 
       listThree.getClass() == listTwo.getClass()); 


     System.out.printf("listOne.getClass() is %s \n",listOne.getClass()); 

     System.out.printf("listTwo.getClass() is %s \n",listTwo.getClass()); 

     System.out.printf("listThree.getClass() is %s \n",listThree.getClass()); 

    } 
} 

及其在控制檯輸出如下:

listOne.getClass() == listTwo.getClass() is false 
listOne.getClass() == listThree.getClass() is false 
listThree.getClass() == listTwo.getClass() is false 
listOne.getClass() is class java.util.ArrayList 
listTwo.getClass() is class Test$1 
listThree.getClass() is class Test$2 
+0

嘗試閱讀這篇文章,你會找到答案: [1]:HTTP:// stackoverflow.com/questions/924285/efficiency-of-java-double-brace-initialization –

回答

1
List<String> listTwo = new ArrayList<String>(){}; 

這產生了anonymous class,其延伸ArrayList<String>。如果你做listTwo instanceof ArrayList,你會發現它實際上是一個ArrayList(好吧,它是一個子類)。這就像你做下面的類:

private class SomeClass extends ArrayList<String> 
{ 
} 

List<String> listThree = new ArrayList<String>() {{}}; 

這就造成像以前那樣一個匿名類,但有一個initialization block(這恰好是空的)。這就像你創建了這個類:

private class SomeClass2 extends ArrayList<String> 
{ 
    { 
     // some code could go here... 
    } 
} 

這可以用於clever-but-confusing的方式,例如,

List<String> listThree = new ArrayList<String>() 
{{ 
    add("hello"); 
}}; 

正如您所預料的那樣,您可以創建一個新列表並添加「hello」。由於「混亂」的部分,我建議不要這樣做。

在您的例子,不過,所有的類功能相同,所以你應該只使用:

List<String> listOne = new ArrayList<String>(); 
+0

感謝您的解釋。這就說得通了。 – MouseLearnJava

0

list1ArrayListlist2ArrayList的匿名子類。 list3是一個具有初始化塊的匿名子類。這意味着涉及三個類別,其中2個是匿名的,稱爲Test$1Test$2。 1和2指的是它們的聲明順序,Test指的是封閉的類。

3

在類的ArrayList這個你箱新的實例

List<String> listOne = new ArrayList<String>();

在這裏定義,從ArrayList的擴展和創建它的

List<String> listTwo = new ArrayList<String>(){};

在這裏,你定義新實例的匿名類另一個匿名類,它從ArrayList擴展並在初始化塊中聲明並創建它的一個實例

List<String> listThree = new ArrayList<String>() {{}};

2

記號new ArrayList<String>(){};實例延伸ArrayList匿名類的對象。

這就是爲什麼你的第二個和第三個變量的classTest$1Test$2(這是怎樣的JVM名匿名類)

0

後兩者的ArrayList匿名子類。在大括號內,您可以重寫通常的原始類的行爲,就像您可以使用正常的繼承一樣。

例如:

List<String> listTwo = new ArrayList<String>(){ 
    this.add("hello user!"); //list is automatically initialized with one element 
    @Override 
    public int size() { 
     return super.size() + 1; //this naughty list lies about its size! 
    } 
}; 

第三個是幾乎相同的第二個,它只有匿名類內部的空的代碼塊。