Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics (List) typing question

I am trying to use a common technique to create objects from Xml. (Xml is legacy, so although there are already libraries to do this, it seemed faster to write this myself.)

I don't understand the compiler's complaint about the generic usage. Code sample:

public void createObjects() {
  List<Object1> objectOnes = new ArrayList<Object1>();
  List<Object2> objectTwos = new ArrayList<Object2>();

  parseObjectsToList("XmlElement1", objectOnes);
  parseObjectsToList("XmlElement2", objectTwos);
}

private void parseObjectsToList(String xmlTag, List<? extends Object> targetList) {
   // read Xml and create object using reflection
   Object newObj = createObjectFromXml(xmlTag);
   targetList.add(newObj)  

/* compiler complains: "The method add(capture#2-of ? extends Object) in the type List<capture#2-of ? extends Object> is not applicable for the arguments (Object)" 
*/

/* If I change method signature to parseObjectsToList(String xmlTag, List targetList)
it works fine, but generates compiler warning about raw type */

}

Thanks for any enlightenment on the subject!

like image 418
Sam Goldberg Avatar asked Jun 28 '26 21:06

Sam Goldberg


2 Answers

The problem you are running into is that, with the bounded wildcard that you have defined, you will be unable to add any element to the collection. From this tutorial:

List<? extends Shape > is an example of a bounded wildcard. The ? stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.

There is, as usual, a price to be paid for the flexibility of using wildcards. That price is that it is now illegal to write into shapes in the body of the method

like image 142
akf Avatar answered Jul 01 '26 02:07

akf


All a wildcard type means is that the actual type parameter T of the List that you pass as the second argument to parseObjectsToList is going to be a subtype of Object. It does NOT mean that the same List will be parameterized with different types.

So now you have a List<T> (called targetList) and you are trying to call targetList.add(Object). This is illegal because Object is not necessarily a subtype of T.

Because you are adding to the List rather than extracting elements from it, use List<Object> and make sure that's exactly what you pass in.

like image 31
danben Avatar answered Jul 01 '26 03:07

danben



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!