0

consider :

public class Parent {

}


public class Child extends Parent {

}


    ArrayList<Parent> ps= new ArrayList<Child>(); \\wont compile
    ArrayList<? extends Parent> ps2= new ArrayList<Child>(); \\works

Why isnt <? extends Parent> assumed by default when using <Parent>? I mean i cant think of a use case in which assuming every Child item is a Parent will cause any unexpected behaviour can you think of any?

EDIT :

a more usefull example :

 public static final void main(String[] args) {
     ArrayList<Child> children=new ArrayList<Child>();
     children.add(new Child());
     children.add(new Child());
     computeSomething1(children); \\doesnt compile
     computeSomething2(children); \\compiles
 }

 public static int computeSomething1(ArrayList<Parent> ps) {
     return 1;
 }
 public static int computeSomething2(ArrayList<? extends Parent> ps) {
     return 1;
 }
Ofek Ron
  • 8,354
  • 13
  • 55
  • 103
  • @ernest_k reread my question i wasnt thinking ArrayList extends Parent> is the same as ArrayList... but i do think that ArrayList should mean the same as ArrayList extends Parent> – Ofek Ron Jul 12 '18 at 09:40
  • 3
    Well, you can't add anything to a list referenced through a variable of type `ArrayList extends Parent>`, which makes it terribly useless. – Dawood ibn Kareem Jul 12 '18 at 09:40
  • You can create like this ArrayList ps= new ArrayList<>(); and add Child instance to that list – janith1024 Jul 12 '18 at 09:43
  • @janith1024 unrelated to my question – Ofek Ron Jul 12 '18 at 09:45
  • @DawoodibnKareem nice observation i edited my question to show you that isnt completely useless – Ofek Ron Jul 12 '18 at 09:46
  • @DawoodibnKareem You can only add `null` to such a list. But this will change nothing in most cases. – LuCio Jul 12 '18 at 09:46
  • Well, a list that can't ever have non-null objects added to it would be one of the more pointless data structures. And if there were no such thing as `ArrayList`, but only `ArrayList extends Parent>`, then that's all you'd ever have. – Dawood ibn Kareem Jul 12 '18 at 09:48
  • @DawoodibnKareem agreed, although it doesnt make sense that the computeSomething1 wont compile... do you see any problem that java designers could avoid by not compiling this? – Ofek Ron Jul 12 '18 at 09:52
  • 3
    If `ArrayList foo = new ArrayList()` compiled, and there's another class, `Blah` which is also a subtype of `Parent`, then how could the compiler stop you from adding a `Blah` to `foo`, which should only admit `Child` objects, not `Blah`objects? – Dawood ibn Kareem Jul 12 '18 at 09:54
  • @DawoodibnKareem It isn't useless. You can iterate over it, so you could have that as a parameter for a method in order to be more permissive – Michael Jul 12 '18 at 09:57
  • @DawoodibnKareem got it. – Ofek Ron Jul 12 '18 at 10:38
  • Because you would then lose the difference between the two syntaxes. – user207421 Jul 12 '18 at 10:42
  • @Michael, yes, you can. But that's not what the question is about. The question is about having ` extends Parent>` assumed by default. That means that you can't ever have a reference of type `ArrayList`. And that means that you can never add anything to the list, ever. Yes, you could iterate over the list if it had some elements; but if you can't ever add any elements to your list, then how will they ever get in there? – Dawood ibn Kareem Jul 12 '18 at 19:54
  • @DawoodibnKareem I know it's not what the question was asking. Your comment is a statement which stands on its own. It does not say it's "useless... in this context". It says "if you can't add to a List variable, it's useless". Well no, that's objectively wrong. A parameter is a type of variable, and it makes absolute sense to use the wildcard type as the type of a parameter. – Michael Jul 13 '18 at 08:44
  • The OP suggested that `ArrayList` should _always_ mean `ArrayList extends Parent>`. That would be useless. I'm not saying that `ArrayList extends Parent>` isn't sometimes a useful data type - of course it is, or we wouldn't have it. But if `ArrayList` _always_ meant `ArrayList extends Parent>` then every list would contain nothing but nulls. _You_ might have a use for such a language, @Michael, but it seems pretty pointless to _me_. – Dawood ibn Kareem Jul 13 '18 at 08:50
  • @DawoodibnKareem There's no need to be patronising. I knew what you were saying after your first reply, you don't need to reiterate it. Please read your comment again as a standalone statement and you will see why it was misleadingly worded. – Michael Jul 13 '18 at 08:57
  • @Michael Why don't you write your own answer to this question, if my contributions upset you so much? – Dawood ibn Kareem Jul 13 '18 at 09:08
  • @DawoodibnKareem No one is upset here except you, friend. I have no doubt that you know what you're talking about, but when you make a comment that gets multiple upvotes and has the potential to mislead beginners, I think it's worth correcting. Fair enough if you don't, but you could easily have deleted it and posted a clearer version in the time you've spent being snarky with me. – Michael Jul 13 '18 at 09:38

1 Answers1

2

If java did this, you could get polluted lists pretty easily. Let's assume that java did what you suggest, and allowed you to assign a List<Child> to a variable of type List<Parent>. Then, this would be possible:

static class Parent {}
static class Child extends Parent {}
static class IllegitimateChild extend Parent {}

public static void main(String args[]) {
    List<Child> children = new ArrayList<>();
    computeSomething(children);
    Child c = children.get(0); //WTF - ClassCastException?? IllegitimateChild is not a Child
}

public static void computeSomething(List<Parent> items) {
    parents.add(new IllegitimateChild());
}

To get around this, java makes you explicitly declare a bounded wildcard if that's what you want. This allows it to catch such errors at compile time.

public static void main(String[] args) {
    List<? extends Parent> items = new ArrayList<Child>();

    items.add(new IllegitimateChild()); // Compiler error
    items.add(new Child()); // Compiler error
}

Both the compiler errors above are Java saying "The type of elements in this list is unknown to me (?), so I can't allow you to put this item in here, as it might violate the contract of some other reference to this list that does know the type." The fact that ? extends Parent rather than just ? only really helps the compiler infer information about the return type of methods (e.g. it knows that it can assign the result of calling items.get(0) to a Parent variable, even though it doesn't know the concrete type).

user31601
  • 2,482
  • 1
  • 12
  • 22
  • Thanks! i got it now... so java designers made this compilation error to avoid inserting other sub classes of Parent to a Chilld array list... and they made it possible to use ? extends Parent by forbidding addition... nice! – Ofek Ron Jul 12 '18 at 10:44
  • 1
    As an aside, if you need a reference to a list that is _only_ for adding elements, and not getting, that's what ` super Blah>` is for. – user31601 Jul 12 '18 at 11:08