2013-06-28 2 views
0

я Java 6 я могу объявить ArrayList следующимИспользование дженериков с правой стороны в Java 6?

Way1: использование дженериков, то есть <Integer> с правой стороны тоже

List<Integer> p = new ArrayList<Integer>(); 

Way2: с помощью алмазного оператора

List<Integer> p = new ArrayList<>(); 

Way3: с помощью общее с левой стороны

List<Integer> p = new ArrayList(); 

Я предпочитаю использовать способ 3 как его краткое описание. Есть ли разница между этими способами? Какой из них мы должны предпочесть и почему?

Обновление: Я знаю, что в java 7-й способ рекомендуется, но мой вопрос в контексте java 6. Какой из них предпочтительнее?

Для меня, путь 3 также говорит p является архаистом целых чисел (тот же передан в пути1). Поэтому я не вижу никакой разницы, кроме того, что в IDE отображается предупреждающее сообщение:

ArrayList - это необработанный тип. Ссылки на общий тип ArrayList<E> должны быть параметризованными

+1

Обратите внимание, что информация в теге [diamond-operator] уже отвечает на ваш вопрос. Просто наведите указатель мыши на этот тег и прочитайте первое предложение его описания: * Оператор алмаза (<>) был введен в Java SE 7 *** –

+0

На самом деле я имел в виду дженерики с правой стороны. см. мое обновление –

+0

какая часть * это доступно с Java 7 * относительно алмазного оператора, которого вы все еще не понимаете? Это похоже на использование дженериков в Java 1.4 или ранее: он не существовал, поэтому вы не можете его использовать. –

ответ

5

Как указано, путь 2 недействителен в 1.6. Таким образом, вопрос в том, есть ли какая-то разница между Way 1 и Way 3. Помимо удобочитаемости, нет.

Возьмите этот код:

import java.util.*; 
class G { 
    public static void main(String [] args){ 
    List<Integer> listOne = new ArrayList<Integer>(); 
    listOne.add(1); 
    int one = listOne.get(0); 

    List<Integer> listTwo = new ArrayList(); 
    listTwo.add(1); 
    int two = listTwo.get(0); 
    } 
} 

Собирать и посмотреть на байткод, используя javap -c

public static void main(java.lang.String[]); 
    Code: 
    // FOR listOne 
     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: iconst_1  
     10: invokestatic #4     // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
     13: invokeinterface #5, 2   // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 
     18: pop   
     19: aload_1  
     20: iconst_0  
     21: invokeinterface #6, 2   // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 
     26: checkcast  #7     // class java/lang/Integer 
     29: invokevirtual #8     // Method java/lang/Integer.intValue:()I 
     32: istore_2  
    // FOR listTwo 
     33: new   #2     // class java/util/ArrayList 
     36: dup   
     37: invokespecial #3     // Method java/util/ArrayList."<init>":()V 
     40: astore_3  
     41: aload_3  
     42: iconst_1  
     43: invokestatic #4     // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
     46: invokeinterface #5, 2   // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 
     51: pop   
     52: aload_3  
     53: iconst_0  
     54: invokeinterface #6, 2   // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 
     59: checkcast  #7     // class java/lang/Integer 
     62: invokevirtual #8     // Method java/lang/Integer.intValue:()I 
     65: istore  4 
     67: return   
} 

Мы можем видеть, что точно такой же байткодом производится в обоих случаях. Обратите внимание, что поскольку Generics не выпекаются в компиляторе, он удаляет информацию после проверки ее во время компиляции и добавляет в инструкции checkcast, чтобы убедиться, что приведения, выполняемые при извлечении объектов, безопасны.

+0

, если way1 и way3 точно так же, почему предупреждение «ArrayList - это необработанный тип. Ссылки на общий тип ArrayList должны быть параметризованы» бросается в way3, хотя и не выбрасывается в way1? предупреждение не имеет никакого смысла для меня. Это? –

+0

Предупреждение дается компилятором, потому что оно не считает, что оно содержит всю информацию. В отличие от других языков программирования в Java нет вывода типа. Тем не менее, вы предоставили достаточно информации для того же кода, который будет выпущен, так как это общий тип на левой стороне, который сообщает компилятору ввести «checkcast». – selig

+0

Way1 и way3 могут скомпилировать один байт-код (спасибо стиранию типа!), Но во время компиляции это не то же самое. Это относится ко всей информации о родовом типе в java: типы предоставляют только проверку типа времени компиляции. Подробнее о том, как way1 и way3 отличаются, см. [Этот ответ] (http://stackoverflow.com/a/4167148/225217) –

1

Там нет никакой разницы, если вы используете Java 7 предпочитают второй способ, но он не доступен в Java 6. Это new addition для Java 7.

+0

Я знаю, что в java 7 рекомендуется отправить путь. Но мой вопрос в контексте java 6.Какой из них предпочтительнее? См. Мое обновление. –

4

Второй путь не представляется возможным в Java 6. это новый способ выводя Generic экземпляра в Java 7.

+0

Это была ошибка типографии, исправила его. –

0

Оба же .Но есть версия разница в обоих.

Но второй путь невозможен в java 6.In Java 7, если мы не объявляем тип в правой части, то по умолчанию он будет иметь тот же тип, что и левая сторона.

http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html

Так как за ваши обновления, если вы должны использовать Java 6, то вы должны использовать way1.

0

Путь 3 использует необработанные типы. Вы никогда не должны использовать необработанные типы. Они должны использоваться только в устаревшем коде.

+0

Для меня, путь 3 также говорит, что p - это arraylist целых чисел (тот же, что передан способом 1). Таким образом, я не вижу никакой разницы, кроме того, что IDE отображает предупреждающее сообщение о сырых типах. С третьим способом мы также не можем добавить строку в arraylist p. Поэтому я не понимаю утверждения: «Путь 3 использует сырые типы». когда я ясно заявлял, что он как арраист из ингрейсов. –

0

Путь 3 не является хорошим. Смешивание Дженерики и сырые типы капризничает, как вы делаете предположение для выполнения о типах, и может работать в ClassCastExceptions как следующий код:

ArrayList b = new ArrayList(); 
b.add(5); 
ArrayList<String> a = new ArrayList(b); 
System.out.println(a.get(0)); 

Так что для Java 6, всегда использовать способ 1