Reputation: 1727
public static <T> List<T> templatizeList(final List list, final Class<T> clazz) {
return (List<T>) list;
}
public static <T> List<T> typeSafeAdd(List<?> from, Class<T> clazz) {
List<T> to = new ArrayList<>();
from.forEach(item -> to.add(clazz.cast(item)));
return to;
}
What is the difference between the two methods? Is one way safer or faster than the other or it does not matter?
Upvotes: 0
Views: 135
Reputation: 4329
There is no way to determine whether the List really should have the generic parameters . You must know beforehand what the parameters should be (or you'll find out when you get a ClassCastException). This is why the code generates a warning, because the compiler can't possibly know whether it is safe.
If you want to support more generic data type, then you can go with
public static <T> List<?> templatizeList(final List list, final Class<T> clazz) {
return (List<?>) list;
}
Otherwise, 2nd option makes sure that it is always of same type but it creates new List object...
So if you are sure then use either your 1st solution or my first option otherwise your second solution is decent removing the part it is creating new object.
Upvotes: 1
Reputation: 4945
Given the discussion, I'd like to suggest an option that combines the best of both worlds: it both localizes the risk of an unsafe cast AND it avoids creating a new List. And it's easy. (I'm making this community wiki since I'm just borrowing others' ideas.)
Step 1: Do the cast for each element from Method 2. Don't do anything with the result, just do the cast. That will ensure that a bad value will be caught right upfront.
Step 2: Do the List
cast from Method 1.
If you know that the List
you got from Hibernate contains only the right type of element, then you can go ahead with Method 1. (The Eclipse JDT (at least prior to Mars) does the same thing in the AST. I have to deal with raw types far more often than I'd like.)
Upvotes: 2
Reputation: 30839
As per Java docs, generics are limited to compile time. They go away once the code compiles, this is called Type Erasure.
Now, regarding the methods, method 1 just adds a cast to the list without checking the type of all the elements present into it. Meaning, you may get an unexpected ClasscastException anywhere in code at runtime if the List is cast to Cat type and what comes out of it is a Dog.
Method 2 creates an entirely new list, it iterates through all the elements and tries to cast each element in target type. Meaning, it would fail if all the elements can't be cast to the target type.
I would say method 2 is safe as it makes sure everything is fine before adding a cast (i.e. localizes the risk). Method 1 may allow List (which contains Cat, Dog, Dinosaur) to be cast to List< Cat > and then, you may get unexpected failures.
This example explains it well.
Upvotes: 6
Reputation: 12953
The difference is that in the first one you return the same list, while the second creates a new list.
I dont think there's a 'safer' of the two- since it eventually cast all list objecta on both, a non T object will cause classCastException on both.
The first is better in my mind- not creating a rather redundant new list
Upvotes: 1