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