0

I want to be able to make a list like so -

List<Object> l = new ArrayList<String>();

The standard library implementation of ArrayList does not allow this. It gives compile time error. So I am writing my own implementation of the ArrayList.

So far I have tried this -

public class ArrayList<Y extends X> implements List<X> {...}
public class ArrayList<X super Y> implements List<X> {...}

which do not compile.

So, how can I write an ArrayList where I would be able to use it like I mentioned above?

List<Object> l = new ArrayList<String>();

People have pointed out this post Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?

But I still don't understand. The reason given was that we want to avoid situations like so -

List<Object> l = new ArrayList<String>();
l.add(new Dog()); 

While this makes sense, I can do a similar kind of thing with Java Arrays which compiles but throws Exception at runtime.

Object o[] = new String[10];
o[0] = new Dog();

So what is the rationale behind allowing the latter code to compile but not the former?

EDIT - Similar question has already been asked as indicated above. This question also helps Why is the ArrayStoreException a RuntimeException?

5
  • 2
    Why does the linked question not answer your question? I mean it explains why Java does not support this kind of syntax. What exactly do you want to achieve if not that? If you write new ArrayList<String>() that list will only accept String and subtypes of it. If you write new ArrayList<Object>() instead, you can add all you want. Commented Dec 5, 2017 at 14:03
  • Are you saying you'd rather have an exception at runtime than a compile error? That doesn't seem to make much sense. Commented Dec 5, 2017 at 14:17
  • No I am not saying that. I am just asking what is the reason behind this. Commented Dec 5, 2017 at 14:17
  • Well, the whole point of generics is to avoid runtime exceptions, so... what other reasons do you need? Commented Dec 5, 2017 at 14:20
  • I need the reason for why is the same thing allowed for Arrays, why not compile time error in that case? Basically what I am asking is why do we have this dual policy, one for Arrays and a different policy for generic ArrayLists? Commented Dec 5, 2017 at 14:24

2 Answers 2

2

Just as your link says, define your List like so:

List<? extends Object> l = new ArrayList<String>();

EDIT

Yes, the reason that

List<? extends Object> l = new ArrayList<String>(); l.add("asda");

doesn't work is to avoid runtime exceptions, because the Type of the List could be is anything extending Object so the compiler treats it as such (could be anything/unknown). However you can still edit the list if you keep a reference to the original.

List<String> strList = new ArrayList<>();
List<? extends Object> objList = strList;
strList.add("asdf");
// Will return Strings that only have the Object interface
Object o = objList.get(0);

The purpose of List<? extends Object> is just to give your code a type guarantee (some type extending Object in this case) and the compiler, thanks to generics, is able to ensure that condition at compile time but it also needs to ensure that you don't violate the original list. Take for example the following code:

List<Integer> intList = new ArrayList<>();
List<? extends Object> objList = intList;
// compile error to protect the original list
objList.add("asdf");

So because the objList is of type ? you can't add a String to it. Even though String is a subclass of Object it might not be (and isn't in this case) the same type as?.

Also don't forget that generic types are gone at runtime because of Type Erasure. Generics are a compile time guarantee.

Also, now I see your true question.

I need the reason for why is the same thing allowed for Arrays, why not compile time error in that case? Basically what I am asking is why do we have this dual policy, one for Arrays and a different policy for generic ArrayLists?

See this question and its related answers regarding that

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

1 Comment

List<? extends Object> l = new ArrayList<String>(); l.add("asda"); Still doesn't work.
0

You can just write

List<Object> l = new ArrayList<Object>();

the type parameter exists only at compile time, so this makes no difference.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.