Второе утверждение оказывается более или менее эквивалентным первому, но только потому, что генерики стираются во время выполнения. Вы получите предупреждение «непроверенное преобразование», поэтому оно мне не нравится.
Лучший способ - использовать статический универсальный метод, подобный этому:
public static <T> List<T> newList() {
return new ArrayList<T>();
}
, а затем сделать
List<String> test = newList();
Это то, что делает Google Collections.
(И вы почти всегда должны объявлять свои списки как List
, а не как ArrayList
. Позволяет легко переключать реализацию позже.)
Редактировать: dribeas спросил в комментариях, какова точная разница между этими двумя объявлениями, и почему я сказал, что они "более или менее эквивалентны". Из-за стирания типа единственным отличием между ними является предупреждение. Вот небольшой фрагмент кода, сравнивающий их:
import java.util.*;
class GenericDeclarationTest {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("");
String s1 = list1.get(0);
List<String> list2 = new ArrayList();
list2.add("");
String s2 = list2.get(0);
}
}
А вот сгенерированный байт-код (напечатанный javap -c GenericDeclarationTest
):
Compiled from "GenericDeclarationTest.java"
class GenericDeclarationTest extends java.lang.Object{
GenericDeclarationTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #4; //String
11: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: aload_1
18: iconst_0
19: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
24: checkcast #7; //class java/lang/String
27: astore_2
28: new #2; //class java/util/ArrayList
31: dup
32: invokespecial #3; //Method java/util/ArrayList."<init>":()V
35: astore_3
36: aload_3
37: ldc #4; //String
39: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
44: pop
45: aload_3
46: iconst_0
47: invokeinterface #6, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
52: checkcast #7; //class java/lang/String
55: astore 4
57: return
}
Как видите (если у вас есть терпение), они идентичны.
Кстати, это может упроститься в Java 7. Существует предложение в Project Coin для «Улучшенного вывода типов для создания общего экземпляра». Если это сделает окончательный вариант, синтаксис будет:
List<String> test = new ArrayList<>();
// or
Map<String, Object> test2 = new HashMap<>();
Не слишком сложно набрать, не так ли?