I try something like this below, but the complier warns me for this type is not applicable for the argument... I know it's not type safe, but any other way to do so?
public void addRow(List<? extends Car> list){
list.add( list.get(开发者_开发问答list.size()-1).getClass().newInstance() );
}
To see the problem, let's expand the problematic method as follows:
public <T extends Car> void addRow(List<T> list) throws InstantiationException,
IllegalAccessException {
T element = list.get(list.size() - 1);
Class<T> clazz = element.getClass(); // Compilation Error Here!
T newInstance = clazz.newInstance();
list.add(newInstance);
}
getClass()
returns Class<? extends Car>
. The compiler is not smart enough to know whether or not the wildcard (?
) matches T
. The programmer can assert that the assignment is, in fact, safe:
public <T extends Car> void addRow(List<T> list) throws InstantiationException,
IllegalAccessException {
T element = list.get(list.size() - 1);
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) element.getClass();
T newInstance = clazz.newInstance();
list.add(newInstance);
}
Of course, now the responsibility for type safety lies with the programmer. Don't forget that even though it might be safe today, future code changes may invalidate the assertion.
The problem is that the return type of getClass()
is Class<?>
. Java is not clever enough to infer the right type in this case - but you are, so use a cast.
Your method declaration calls for a List whose type is a class that extends Car. Yet when you call newInstance the compiler doesn't know what the sublcass is so it determines the class to be Car as well. Well you can't add a Car to a List that is expecting a subclass of Car.
If it is acceptable for your List to store Cars and not just the subclass why not just write the method like this..
public void addRow(List<Car> list) throws Exception {
list.add( list.get(list.size()-1).getClass().newInstance() );
}
From Oracle's own documentation as to why your approach doesn't work...
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. For instance, this is not allowed:
public void addRectangle(List<?
extends Shape> shapes) {
shapes.add(0, new Rectangle()); // Compile-time error!
}
You should be able to figure out why the code above is disallowed. The type of the second parameter to shapes.add() is ? extends Shape-- an unknown subtype of Shape. Since we don't know what type it is, we don't know if it is a supertype of Rectangle; it might or might not be such a supertype, so it isn't safe to pass a Rectangle there.
My advice is to rewrite your method signature as I have provided
精彩评论