ArrayList <Integer> allows you to add lines?
I came across the following code, a simple example of adding items to a List
List list = new ArrayList<Integer>(); ListIterator<Integer> litr = null; list.add("A"); list.add("1"); list.add(5); litr = list.listIterator(); while(litr.hasNext()){ System.out.println("UIterating " + litr.next()); } I expected it to throw a ClassCastException , but rather wrote it to the console
A 1 5 which looks weird. When I tried:
List<Integer> list = new ArrayList<Integer>(); I got a compile time error.
I would appreciate it if anyone could explain how String objects are added to an ArrayList
You have assigned a new ArrayList to the untyped list. Restrictions of a general type do not apply to an untyped list, this will allow you to put everything you need into it. The compiler does not track that your untyped list refers to what was declared with a generic type.
In any case, this will not raise a ClassCastException, generics only affect compilation. At runtime
The case when you put a type in a list variable:
List<Integer> list = new ArrayList<Integer>(); is preferred, it should generate a compiler error saying that you are putting the wrong type in the collection.
It describes how legacy, non-generic code and generic code interact in this article :
In native code, the collection will always be followed by a type parameter. When a generic type of type Collection is used without a type parameter, it is called a raw type.
For most people, the first instinct is that Collection really means
Collection<Object>. However, as we saw earlier, it is not safe to pass theCollection<Part>to the place where theCollection<Object>is required. More precisely, the Collection type denotes a collection of some unknown type, just likeCollection<?>.But wait, that is not the case either! Consider a call to
getParts(), which returns a collection. This is then assigned to k, which corresponds toCollection<Part>. If the result of the call isCollection<?>, The assignment will be an error.In reality, the assignment is legal, but it generates an unverified warning. A warning is necessary because the fact is that the compiler cannot guarantee its correctness. We have no way to check outdated code in
getAssembly()to make sure that the truly returned collection is a collection of parts. The type used in the code is Collection, and anyone can legally embed all kinds of objects in such a collection.So, isn't that a mistake? Theoretically, yes; but in fact, if generic code uses legacy code, this should be allowed. This is for you, the programmer, to make sure that the assignment is safe in this case, because the
getAssembly()contract says that it returns a collection of parts, although the type signature does not show this.
This is possible due to the way generic tools are implemented in Java - using the erasure type and because Java supports raw types for backward compatibility with older versions of Java (1.4 and older).
There are only general concepts in your source code. The compiler uses them to check types at compile time, but then discards the generics. At run time, a List<Integer> is just a List object, and it does not know that it is a list that should contain only Integer objects.
Java supports the use of raw types such as List instead of List<Integer> for backward compatibility with older versions. When you use a raw type, as you do in your code above, you get a compiler warning. You should not use raw types in new code — only ever use them when you need to deal with old code that you cannot change.
The combination of raw and erase types allows you to put object types in lists that you should not insert there.
Since List at run time does not know anything about the type its element should have, it does not check anything, so you will not get a ClassCastException .