tags:

views:

60

answers:

3

What I mean is, in the code below:

class base {

}

class derived extends base {

}

class WTF {

    public void func(List<base> list) {

    }

    public void tryit() {
        func(new List<base>()); // ok
        func(new List<derived>()); // not ok
    }
}

But if the function simply took an object of base, it could take a derived object. Why is this?

+11  A: 

func needs to be defined as

public void func(List<? extends base> list) { ... }

This is because a List<derived> is not actually a List<base>, because a List<base> allows any kind of base in it, while a List<derived> only allows derived and its subclasses. Using ? extends base ensures that you can't add anything but null to the List, since you're not sure what subclasses of base the list might allow.

As an aside, you should try to follow standard Java naming conventions... classes starting with lowercase letters look strange, like they're primitives.

ColinD
+3  A: 

This is because if passing in a List<derived> was allowed, func() would be able to add base-typed elements to the list, thus invalidating the generic contract of the list (which should only allow for derived-typed contents)

if on the other hand you define func as

public void func(List<? extends base> list)

you can still retrieve base-typed elements from list, but just won't be able to add any new elements to it, which is exactly the behavior you want.

Luke Hutteman
+1  A: 

To explain this behaviour of java, look at this example

void addItem(List<Base> list) {
    list.add(new Base());
}

List<Base> l1 = new ArrayList<Base>();
addItem(l1);
Base b = l1.get(0);

List<Derived> l2 = new ArrayList<Derived>();
addItem(l2);
Derived d = l2.get(0); // Would cause runtime exception.

That's why this code will not compile in the first place.

Arian