2

I ask this question because of a discussion about one answer here on Stack. The statement is the following:

Given the following code:

List<?> list =new ArrayList<Integer>();

Why can't we do:

Integer e = 2;
list.add(e);

This throws a compiler error, despite the fact that we instantiated the list as an ArrayList<Integer>.

Why is that ?

1
  • 2
    because you explicitly have taken information away from the compiler, the compiler does not know the actual type of the instance at runtime, it knows only the type you write down: List<?>. Commented Apr 11, 2018 at 15:40

2 Answers 2

4

Because a List<?> could be any sort of List (List<String> for example). And the compiler should not permit adding the wrong type to a list.

However, if you know the actual class then you can do a class cast at runtime:

((List<Integer>)list).add(e);

Code like this should be avoided since it can generate a ClassCastException if an unexpected type is encountered at runtime. To make matters worse (as noted by luk2302), our ClassCastException might only occur in an entirely different area of the code-- namely, when we are retrieving something from the list.

A better approach

If you know that the list will be of a specific type or a superclass of that type, then you could define the variable using a bounded wildcard:

List<? super Integer> list;
Integer e = 2;

list = new ArrayList<Integer>();
list.add(e);

list = new ArrayList<Number>();
list.add(e);

list = new ArrayList<Object>();
list.add(e);

This approach, as noted by M. Prokhorov, allows us to avoid the need for an inadvisable cast.

Sign up to request clarification or add additional context in comments.

3 Comments

Note that the code shown will not produce a ClassCastException, not even for List<String> - it will run just fine, only when retrieving something from the list a ClassCastException might occur.
Should also note that compiler will permit adding elements to a list which is defined as ? super T, where it would allow adding elements of T or any superclass thereof (except when T is interface, you can't add Object to the mix, that one won't work).
I would make the casting approach the last part of the answer, rather than the first part. No one should ever be doing an unsafe cast like that.
0

Just create an Arraylist of and they will let you add all, because Integer, String and Boolean are child or in other words Object class is their parent.

1 Comment

It does not the "why" question, tho. The question is not here to find a workaround (I already have one), it is to provide information on why this behavior happens. Remember it when it comes to answering questions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.