3

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

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
M Sach
  • 33,416
  • 76
  • 221
  • 314
  • 1
    Note that the info in the [diamond-operator] tag already answers your question. Just hover your mouse over this tag and read the first sentence of its description: *The diamond operator (<>) was **introduced in Java SE 7*** – Luiggi Mendoza Jun 28 '13 at 05:40
  • Actually i meant generics on right hand side. see my update – M Sach Jun 28 '13 at 05:43
  • what part of *this is available since Java 7* regarding diamond operator you still don't understand? It's like using generics in Java 1.4 or prior: it didn't exist so you can't use it there. – Luiggi Mendoza Jun 28 '13 at 05:44
  • After your edit in *Way2*, now you're initializing a `List` with a raw `ArrayList` which has no sense... – Luiggi Mendoza Jun 28 '13 at 05:46
  • Thats what i am trying to understand whats the difference btw List p = new ArrayList() and List p = new ArrayList(). You said "After your edit in Way2, now you're initializing a List with a raw ArrayList which has no sense..". Why it does not make any sense when way 2 is allowed in java 6. – M Sach Jun 28 '13 at 05:51
  • To me way 2 also says p is an arraylist of integers (same conveyed by way1 ). So i find no difference except IDE displays warning message? – M Sach Jun 28 '13 at 05:53
  • Now that your question looks clearer, the warning is not from your IDE, is from the Java compiler. It means that the code will behave as expected but it would be better to not use raw classes when you can use the power of generics and avoid adding class object references that do not belong to the class you expect to hold in your generic class. – Luiggi Mendoza Jun 28 '13 at 05:59
  • You said "using no generics at all in way3" But thats not correct we are using generics in way 3 also but only at left hand side which works exactly in the same fashion whether we declare generics on right hand side or not.With way 3 also, we can not add string in arraylist p. So i find no difference. – M Sach Jun 28 '13 at 06:03
  • @Luiggi Mendoza can you throw some light on my last comment – M Sach Jun 28 '13 at 09:10

7 Answers7

6

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.

selig
  • 4,834
  • 1
  • 20
  • 37
  • if way1 and way3 are exactly same why warning "ArrayList is a raw type. References to generic type ArrayList should be parameterized" is thrown in way3 though not thrown in way1? warning does not make any sense to me.Does it? – M Sach Jun 29 '13 at 02:17
  • The warning is given by the compiler because it doesn't think it has all the information. Unlike in other programming languages there is no type inference in Java. However, you have given enough information for the same code to be produced as it is the generic type on the left handside that tells the compiler to introduce the `checkcast`. – selig Jul 16 '13 at 06:22
  • Way1 and way3 may compile down to the same byte code (thank you type erasure!) but these are not the same during compilation. This is true of all generic type information in java: types only provide compile time type checking. For more on how way1 and way3 differ see [this answer](http://stackoverflow.com/a/4167148/225217) – Brice Roncace Mar 14 '14 at 17:46
4

The second way is not possible in Java 6. It is the new way of inferring Generic instance in Java 7.

Kaushik
  • 3,371
  • 3
  • 23
  • 32
1

There is no difference, if you are using java 7 prefer the second method, but is it not available in java 6. It is a new addition to java 7.

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
  • I know in java 7 send way is recommended. But my question is in context of java 6.Which one is preferrable? See my update. – M Sach Jun 28 '13 at 05:41
0

Both are same but way2 is available from java 7

Siva
  • 1,938
  • 1
  • 17
  • 36
0

Both are same .But there are version difference in both of this.

But second way is not possible in java 6.In Java 7 if we not declare type in right side then by default it will take same type as left side.

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

So as per your updates, if you have to use Java 6,then you should use way1.

Manish Doshi
  • 1,205
  • 1
  • 9
  • 17
0

Way 3 uses raw types. You should never use raw types. They should only be used in legacy code.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • 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 about raw types.With way 3 also, we can not add string in arraylist p . So i do not understand the statement "Way 3 uses raw types." when i have clearly declared it as arraylist of intgers. – M Sach Jun 29 '13 at 01:22
0

Way 3 is not good. Mixing Generics and raw types is naughty, as you are making an assumption for runtime about types, and can run into ClassCastExceptions like the following code:

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

So for Java 6, always use way 1

rewolf
  • 5,561
  • 4
  • 40
  • 51