K Man
K Man

Reputation: 628

Why am I still able to add any Object to a List with a raw-type reference type after changing its object type to a generic?

I declared and initialized myList with a raw reference type of List and a raw object type of ArrayList. Then, I re-referenced myList to a new, generic ArrayList of Longs. I thought that adding anything other than a Long to this list would thus cause an error.

List myList = new ArrayList();
myList = new ArrayList<Long>();
myList.add(3.4d);
myList.add(4.0f);
myList.add("weird");
myList.add('w');
System.out.println(myList);

However, this runs without an error or exception. How is this legal?

Upvotes: 0

Views: 231

Answers (2)

Bohemian
Bohemian

Reputation: 425198

How is this legal?

Because the java compiler only considers the declared type, which in this case is the raw type List:

List myList

that can hold any type of object.

The assignment myList = new ArrayList<Long>() has no effect on the declared type of myList.

Upvotes: 2

SephB
SephB

Reputation: 627

If you declare it as List<Long> you will get static compile time type checking. Do to type erasure the JVM does not know anything about those types at runtime.

List<Long> myList = new ArrayList<>();
myList.add("foo");

Will give a compilation error while:

public void breakGeneric(List list) {
    list.add("foo");
}
....
List<Long> myList = new ArrayList<>();
breakGeneric(myList);

will add "foo" to a list no matter what type type is. Most IDEs will worn you about loosing the generic type.

Having the type in the new statement new ArrayList<Long>() would only have an effect if you chain off of that statement ie new ArrayList<Long>().add("foo"). That is the only way that a generic type only in the new statement will cause a compilation problem.

Upvotes: 2

Related Questions