2013-11-21 3 views
2

Я пытаюсь создать экземпляр списка с помощью следующих способов:разница Тип между подобными декларациями ArrayList

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

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

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

только listOne инициализируется как java.util.ArrayList, но listTwo и listThree нет.

Что происходит при инициализации 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"); 
}}; 

Это, как и следовало ожидать, создает новый список и добавляет к нему «привет». Я бы рекомендовал против этого из-за «запутанной» части этого.

В вашем примере, однако, все классы функционируют так же, так что вы должны просто использовать:

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

Спасибо за объяснение. В этом есть смысл. – MouseLearnJava

0

list1 является ArrayList. list2 является анонимным подклассом ArrayList. list3 - анонимный подкласс с блоком инициализации. Это означает, что есть три класса, из которых 2 являются анонимными, которые называются Test$1 и Test$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.

Вот почему class вашей второй и третьей переменной являются Test$1 и Test$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! 
    } 
}; 

Третий практически идентичен второму, он имеет только пустой блок кода внутри анонимного класса.

Смежные вопросы