I have a List that is guaranteed to contain just one type object. This is created by some underlying code in a library that I cannot update. I want to create a List
You can simply cast the list:
List raw = new ArrayList();
List<String> generic = (List<String>) raw;
The best and safest way is to use java.util.Collections method 'checkedList(List list, Class type)'
With this method, all of the items in your old List will be checked as early as possible.
If you just cast to List<T>
in any old place you will get an "unchecked" compiler warning. We resolved that by moving it to a utility method.
public class Lists {
@SuppressWarnings({"unchecked"})
public static <T> List<T> cast(List<?> list) {
return (List<T>) list;
}
}
Caller now gets no warning, e.g.:
for (Element child : Lists.<Element>cast(parent.getChildren())) {
// ...
}
That checkedList
utility is in theory a great idea, but in practice it sucks to have to pass in the class you expect. I hope Java will get runtime generic typing information eventually.
Try this:
List<ObjectType> objectsWithType = Arrays.asList((ObjectType[])wildcardObjects).toArray());
But remember that this will produce a fixed length List. If you try to add or remove element from this list, it will throw an error. So be always careful while using Arrays.asList().
When inter-operating with legacy code that doesn't specify type parameters for generic types, use a wildcard. For example, suppose you are calling a method in an older library that simply returns a raw Collection
:
Collection getItems();
In your code, assign the result to a variable declared with a wildcard:
Collection<?> items = widget.getItems();
This way, you preserve type safety so you won't get any warnings.
The legacy code might specify (in a comment, most likely) what the generic parameters should be. For example:
/**
* @return the items, as a Collection of {@link Item} instances.
*/
Collection getItems();
In this case, you have a choice. You can cast the result to a Collection<Item>
, but if you do so, you are relying 100% on the third-party library, and discarding the assurance of Java generic types: that any ClassCastException
raised at runtime will occur right at an explicit cast.
What if you don't fully trust the third-party library, but still need to produce a Collection<Item>
? Then create a new collection, and add the contents after casting them to the expected type. That way, if there is a bug in the library, you find out about it right away, rather than having some code far away and much later mysteriously blow up with a ClassCastException
.
For example:
Collection<?> tmp = widget.getItems();
Collection<Item> items = new ArrayList<Item>(tmp.size());
for (Object o : tmp)
items.add((Item) o); /* Any type error will be discovered here! */
For a case where the type parameter isn't known at compile-time, you can use the type-checked collection factories of the Collections
class.