This works/matches your requirements - except for throwing a ClassCastException (if you really want that behaviour, you can include it in the checkedCast method yourself):
import java.util.*;
public class CheckedCast {
public static <GenB, GenA extends GenB, CollA extends List<GenA>> List<GenB> checkedCast(CollA iterable, Class<GenB> clazz){
return (List<GenB>)iterable;
}
public static <GenB, GenA extends GenB, CollA extends Set<GenA>> Set<GenB> checkedCast(CollA iterable, Class<GenB> clazz){
return (Set<GenB>)iterable;
}
static class One {}
static class Two extends One {}
static class Three {}
public static void main(String[] args) {
ArrayList<Two> test1 = new ArrayList<Two>();
List<One> test2 = checkedCast(test1, One.class);
// Shouldn't compile...
ArrayList<One> aa = checkedCast(test2, One.class); // output is ArrayList
List<Two> bb = checkedCast(test2, Three.class); // Three is not superClass of Two
ArrayList cc = checkedCast(new HashSet(), Integer.class); // Set cannot become List
ArrayList<One> dd = checkedCast(new LinkedList<One>(), One.class); // ArrayList is not superClass of List
}
}
Updated to match new requirement: ArrayList xs = checkedCast(new HashSet(), Integer.class) - shouldn't compile
Update: updated to assert returned Collection generic type extends input Collection's generic type.