3

I have read that the following code snippet will result in a compiler error

void tryAddingToList(List<? extends SuperType> list) {
  list.add(new SubType());
}

Now my question is: Who exactly sets the restriction and how is the restriction set? Does the compiler specifically check for the add method call in such a method implementation?

If yes, what if I implement my own List and instead of add, introduce a new addToList method that does the same thing as add, and call that in the tryAddingToList method?

Even better, what if I implement my get method such that it also "secretly" adds something to the list (don't ask me why anyone would do that; I'm just curious).

Community
  • 1
  • 1
Jagat
  • 1,392
  • 2
  • 15
  • 25
  • The compiler won't let you add to a list which has a bounded wildcard. That's a rule. As for your second question, will your own List implementation be parameterized or not? – Joeblackdev Mar 14 '12 at 17:07

3 Answers3

1

You should cast SubType to SuperType explicitly. Because not all objects of SuperType are SubType(may be typed other sub-classes). This may give you some hint. Good luck.

Community
  • 1
  • 1
Summer_More_More_Tea
  • 12,740
  • 12
  • 51
  • 83
  • Thanks! But my question isn't about how to make that code snippet work. – Jagat Feb 25 '12 at 07:54
  • 1
    That's not what the question is asking. It's also wrong, because `SubType` can always be implicitly cast to `SuperType`: the compile error is because the compiler doesn't know what concrete subclass the generic type refers to. – Cameron Skinner Feb 25 '12 at 07:55
  • 1
    This is also a common way to "declare" some collection as read-only. Don't be surprised if you see something like `List extends String> foo` - it's just a read-only List of Strings. – Alexander Pavlov Feb 25 '12 at 07:56
  • @Jagat You're welcome. Sorry for can't help you more. @Cameron Thanks for pointing the implicit cast out, then is any differences between `void tryAddingToList(List extends SuperType> list)` and `void tryAddingToList(List list)` as that declared in another post I referred? – Summer_More_More_Tea Feb 25 '12 at 08:07
  • @Summer_More_More_Tea There's no difference. T, in your example, is used just to capture the actual type so that you can reuse the actual type in your method. For instance, to create a List for some purpose. – Jagat Feb 25 '12 at 09:03
  • @AlexanderPavlov Again, how is it marked read only? How does the compiler know that a method is actually "writing"? Perhaps it knows that `add` in the List interface is a method that modifies the List. But I could always come up with a method that also writes to the List, in my own implementation. – Jagat Feb 25 '12 at 09:08
  • @Jagat I was only saying that you cannot add to a list declared as `List extends Foo>`. [This great wildcards tutorial from Oracle](http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html) explains this (look up `public void addRectangle(List extends Shape> shapes)` there). – Alexander Pavlov Feb 25 '12 at 11:49
  • It's not correct to think of List extends SuperType> as a read only list. You can still add to it nulls, remove elements, sort it, etc. Use Collections.unmodifiableList for this purpose – dcernahoschi Feb 25 '12 at 11:49
  • @dcernahoschi: Absolutely, this is not the canonical way to declare unmodifiable collections, I was just referring to a trick developers use in APIs to let their users know some collection should not be modified (notice, I quoted the "declare" verb in my comment.) – Alexander Pavlov Feb 25 '12 at 11:55
  • @AlexanderPavlov ah,ok. I missed the quotes. – dcernahoschi Feb 25 '12 at 12:13
1

Yes, it's indeed the compiler that applies the restriction. Most of the information (not all) will be erased when actually compiled to byte code. You should interpreted generics as extra information for the developer, so we don't make silly mistakes.

M Platvoet
  • 1,679
  • 1
  • 10
  • 14
1

You should use super instead of extends here.

void tryAddingToList(List<? super SubType> list) {
    list.add(new SubType());
}

Assume there are 3 types SuperType, SubType1, SubType2. In your original code, List<? extends SuperType> could be List<SubType2>, and you can't add a SubType1 to List<SubType2>.

Bob Wang
  • 606
  • 4
  • 8
  • Sorry, but that doesn't answer my question, which is about how the restriction set by `? extends` is enforced. – Jagat Feb 27 '12 at 08:26