I have a List that contains a certain superclass (like Vehicle), and I would like to write a method that returns the objects in that list that are instances of a certain subclass (like Car).
So far I have this, but it generates a typical "unchecked" operation compiler warning:
public <T extends Vehicle> List<T> getVehiclesOfType(Class<T> type) {
List<T> result = new ArrayList<T>();
for (Vehicle vehicle : getVehicles()) {
if (type.isAssignableFrom(vehicle.getClass())) {
result.add(type.cast(vehicle)); // Compiler warning here
// Note, (T)vehicle generates an "Unchecked cast" warning (IDE can see this one)
}
}
return result;
}
Warning: Note: Test.java uses unchecked or unsafe operations.
I'm ok with any other method of accomplishing this (I couldn't find anything in Collections, but it's possible some JDK method can do it), but ideally it would provide the following interface:
List<Car> cars = getVehiclesOfType(Car.class);
I would like to know why I was receiving a compiler warning on the original code, though.
You're getting a warning because there's no way for the compiler (or the IDE) to know that the cast is safe, without understanding the meaning of isAssignableFrom(). But isAssignableFrom() isn't a language feature, it's just a library method. As far as the compiler's concerned, it's the same as if you'd said
if (type.getName().contains("Elvis")) {
result.add(type.cast(vehicle));
}
However, you know what isAssignableFrom() means, so you know it's safe. This is exactly the sort of situation @SuppressWarnings is meant for.
How about this?
if (type.isInstance(vehicle)) {
result.add((T)(vehicle));
}
Does the compiler still complain like that?
But if I were you I'd use Guava, that will make your method a one-liner:
public <T extends Vehicle> List<T> getVehiclesOfType(Class<T> type) {
return Lists.newArrayList(Iterables.filter(getVehicles(), type));
}
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