Search code examples
javagenericsdiamond-operator

Using Generics on right hand side in Java 6?


I java 6 i can declare the arraylist as follows

Way1: using generics i.e <Integer> on right hand side too

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

Way2: using the diamond operator

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

Way3: using generic only at left side

List<Integer> p = new ArrayList(); 

I prefer to use way 3 as its brief. Is there any difference between these ways? Which one we should prefer and why?

Update:- I know in java 7 second way is recommended but my question is in context of java 6. Which one is preferable?

To me, way 3 also says p is an arraylist of integers (same conveyed by way1). So I find no difference except the fact IDE displays warning message:

ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized


Solution

  • As has been pointed out, Way 2 isn't valid in 1.6. So the question is, is there any difference between Way 1 and Way 3. Apart from readability, no.

    Take this code:

    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);
      }
    }
    

    Compile it and look at the bytecode using 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        
    }
    

    We can see that the exact same bytecode is produced in both cases. Note that as Generics aren't baked in the compiler throws away the information after checking it at compile time and adds in checkcast instructions to make sure the casts it does when retrieving objects are safe.