Why are java generics so tricky? I thought I finally understood, but eclipse gives me an error at the line in somOtherMethod below using either of the getOuterList methods below.
protected List<?> getOuterList() {
// blah blah
}
protected List<? extends Object> getOuterList() {
// blah blah
}
protected void someOtherMethod() {
...
getOuterList().add((MyObject)myObject); //compile error
...
}
UPDATE: ok - so I understand the error now. It was lack of understanding on my part of what List<?>
or List<? extends SomeObject>
really means. In the former case, I thought it meant a list that could contain anything. In the latter case, I assumed it was a list of a bunch of objects that extend SomeObject. The proper representation of my understanding would just be List<Object>
and List<SomeObject>
(w/out the extends). I thought extends helped me solve a problem which they don't. So here's where my real problem lies:
public interface DogKennel {
public List<Dog> getDogs();
}
public class GreyHoundKennel implements DogKennel {
protected List<GreyHound> greyHounds;
public List<GreyHound> getGreyHounds() {
return this.greyHounds;
}
public List<Dog> getDogs() {
// Is there no way to handle this with generics
// w/out creating a new List?
return getGreyHounds(); //compiler error
}
}
Description. Java generics provides a way to parameterize types, say class MyClass<T> { ... } This allows the user to substitute an arbitrary Java Class for T when a MyClass object class is instantiated. Generics were introduced in Java 1.5.
Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.
Both ArrayList and vector are generic types.
This declaration:
List<?> getOuterList() { }
is telling the compiler "I really don't know what kind of list I'm going to get back". Then you essentially execute
list<dunno-what-this-is>.add((MyObject)myObject)
It can't add a MyObject to the List of something that it doesn't know what type it is.
This declaration:
protected List<? extends Object> getOuterList() { ... }
tells the compiler "This is a list of things that are subtypes of Object". So again, of course you can't cast to "MyObject" and then add to a list of Objects. Because all the compiler knows is that the list can contain Objects.
You could however, do something like this:
List<? super MyObject>.getOuterList() { ... }
and then successfully add a MyObject. That's because now the compiler knows the List is a list of MyObject, or any supertype of MyObject, so it can surely accept MyObject.
Edit: As for your DogKennel example, this code snippet I think does what you want:
protected List<GreyHound> greyHounds;
// We only want a List of GreyHounds here:
public List<GreyHound> getGreyHounds() {
return this.greyHounds;
}
// The list returned can be a List of any type of Dog:
public List<? extends Dog> getDogs() {
return getGreyHounds();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With