I am building some generic codes which returning a collection of any type of object. Here is my build:
public class Util{
public static <T, R extends Collection> R a(Collection<T> collection) {
return (R) collection;
}
public static <T> List<T> listWith(T... items) {
return Arrays.asList(items);
}
public static <T> Set<T> setWith(T... items) {
return new HashSet<>(Arrays.asList(items));
}
}
My Idea is from this Util class I can create any list or set of any object type, something like:
List<String> list = a(listWith("str1", "str2"));
Set<Object> set = a(setWith(new Object(), new Object()));
I have now two questions:
- How can I restrict the type of the Obj in the left to be the same as the Obj type of the parameter passed to the
listWithmethod? Because right now I can do something like :Set<String> set = a(setWith(new Object(), new Object()));without any compile error - How can I restrict the return type of the
amethod to be only class that extends the Collection. Right now I can do something like:User user = a(listWith("test"));also without compile error but then it will throw an casting exception. I did try above with return type asR extends Collectionbut it did not success
<T, R extends Collection<T>>and you will get compile time error.ais that the type is chosen at the call site. For example, you could do bothList<String> list = a(something); Set<String> set = a(something);- and at least one of those will likely fail, becausesomethingis likely not both aSetand aList. In that case, it is better just to do an explicit cast where you would otherwise invokea.<T, R extends Collection<T>> R a(Collection<T> collection)but why not returning it directly in listWith and setWith methods? Also why wrapping asList with a different name? asSet would be a good enhancement.