Sherin Syriac
Sherin Syriac

Reputation: 495

Generics Declaration differences in Java

 List<String> v = new ArrayList<String>();

I understand the generics helps you declare that the ArrayList() has Objects of type String. My question is how is the following one different from the above?

 List<String> v = new ArrayList();

or the one below different from others

List v = new ArrayList<String>();

Upvotes: 3

Views: 342

Answers (5)

assylias
assylias

Reputation: 328923

public static void main(String[] args) throws Exception {
    List<String> list1 = new ArrayList<String>();
    List<String> list2 = new ArrayList(); //This is equivalent to list1 but with compilation warning
    List list3 = new ArrayList<Integer>(); //This is equivalent to list3 = new ArrayList<Object>()
    //list1.add(new Object()); //does not compile
    //list2.add(new Object()); //does not compile
    list3.add(new Object()); //this is fine
    list1 = list3; //ok, but
    System.out.println(list3.get(0)); // this is fine
    System.out.println(list1.get(0)); //Runtime error: ClassCastException
    //List<Object> list5 = list1; //does not compile        
    List<Object> list5 = list3; //ok
}

Upvotes: 1

Affe
Affe

Reputation: 47994

List<String> v = new ArrayList();

This one isn't really functionally different. The type parameter on the right side doesn't really do anything. It's used as a matter of style and to avoid the use of a Raw type, which is considered a programming error. In fact, in Java 7 it has been enhanced so you can just do this: List<String> v = new ArrayList<>(); and not have to repeat yourself on the right hand side.

List v = new ArrayList<String>();

The list with no type parameter is called a Raw Type. It is generally considered a programming error to declare a Raw Type in new code that is using generics. Basically there is no type checking going on at all when you declare it this way, you can put anything in that list.

Java generics are a compile time check. So it is the type of the reference at compile time that matters. If your reference is of type Raw List it doesn't matter what you declared on the right hand side, that is what the compiler will check against.

List<String> isn't really a "List that has Strings." It is a "List that I have asked the compiler to return errors and/or warn me if I put something in there that isn't a String. If you ignore compiler warnings, it is perfectly possible to get stuff in there that isn't a String.

Upvotes: 4

Oscar Castiblanco
Oscar Castiblanco

Reputation: 1646

List v = new ArrayList();

It is before java 5 way of declaring a list.

List<String> v = new ArrayList<String>();

It uses generics, introduced in java 5. It adds compile-time type safety.

List<String> v = new ArrayList<>(); 

is just an optimization introduced in java 7. It just simplifies the code by maintaining the type safety

Upvotes: 1

Attila
Attila

Reputation: 28802

In the first and third case (new ArrayList<String>()) you instantiate an ArrayList that can hold String instances

In the second case (new ArrayList()) you instantiate an ArrayList that can hold Object instances (that is instances of any type -- even mix & match)

In the first and second case (ArrayList<String> v) you declare an instance of ArrayList that can hold String instances

In the third case (ArrayList v) you declare an instance of ArrayList that can hold instances of Object.

The problem with the second case is that if you were to get hold of a "raw" ArrayList (like the one instantiated), then it could hold anything theoretically; not just String instances, which is what the users of the declaration expect.

Similarly, in the third case, you create an ArrayList that is supposed to hold Strings, but the users of the declaration do not know that and might try to put other object instances in it

Note: of course under the hood, in the JVM, the generic type information is lost, so there are no differences in terms of execution, but for programming type safety, the compiler will flag the incorrect use. This way, there is no need to dynamically check/ensure the type of the objects put into/coming out of the list -- you can assume they are the correct type, because the compiler ensured this

Upvotes: 0

Nathaniel Ford
Nathaniel Ford

Reputation: 21269

These all compile, and are all valid. The second case is likely only going to throw a warning - you won't be able to add anything that isn't a string due to List<String>. In the third case you have the opposite problem. You CAN add things that aren't Strings, but may run into a runtime exception as a result.

Upvotes: 0

Related Questions