3

我java 6我可以声明arraylist如下

Way1:使用泛型,即<Integer> 在右手边

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

方式2:使用菱形算子

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

Way3:仅在左侧使用泛型

List<Integer> p = new ArrayList(); 

我更喜欢使用方式 3 作为它的简介。这些方式有什么区别吗?我们应该更喜欢哪一个,为什么?

更新:-我知道在 java 7 中推荐第二种方式,但我的问题是在 java 6 的上下文中。哪一种更可取?

对我来说,方式 3 还说p 是整数的数组列表(与方式 1 传达的相同)。所以我发现除了IDE显示警告消息之外没有区别:

ArrayList 是一种原始类型。对泛型类型的引用ArrayList<E>应该被参数化

4

7 回答 7

6

正如已经指出的那样,方式 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        
}

我们可以看到在这两种情况下都产生了完全相同的字节码。请注意,由于泛型没有在编译器中烘焙,因此在编译时检查信息后会丢弃信息并添加checkcast指令以确保它在检索对象时所做的强制转换是安全的。

于 2013-06-28T08:12:47.977 回答
4

第二种方法在 Java 6 中是不可能的。它是 Java 7 中推断通用实例的新方法。

于 2013-06-28T05:45:02.577 回答
1

没有区别,如果您使用的是 java 7,则更喜欢第二种方法,但它在 java 6 中不可用。它是java 7的新增功能。

于 2013-06-28T05:38:42.693 回答
0

两者都是相同的,但way2可从 java 7 获得

于 2013-06-28T05:41:12.870 回答
0

两者都是相同的。但这两者都存在版本差异。

但是第二种方式在 Java 6 中是不可能的。在 Java 7 中,如果我们不在右侧声明类型,那么默认情况下它将采用与左侧相同的类型。

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

所以根据你的更新,如果你必须使用 Java 6,那么你应该使用 way1。

于 2013-06-28T05:57:41.477 回答
0

方式 3 使用原始类型。你永远不应该使用原始类型。它们应该只用于遗留代码。

于 2013-06-29T00:25:45.367 回答
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

于 2015-01-21T02:12:33.007 回答