采用`T扩展Iterable'并返回T <e>?</e>的方法

时间:2014-05-13 02:50:39

标签: java generics

如何编写一个方法,该方法采用某种T类型的参数(Iterable的实例),以及参数Class<E>,并返回{{1} }?

T<E>

我想这样用:

public static <...> ... checkedCast(T iterable, Class<E> clazz) {
    // Check elements and throw ClassCastException if invalid

    @SupressWarning("checked")
    ... cast = (...)iterable;
    return cast;
}

我知道我可以使用覆盖执行此操作,但这需要我为每种类型编写覆盖:

// This should compile
ArrayList<?> a = ...;
ArrayList<String> b = checkedCast(a, String.class);

// So should this
HashSet<Number> c = ...;
Set<Integer> d = checkedCast(c, Integer.class);

// This shouldn't compile
b = checkedCast(a, Integer.class);

// This shouldn't compile
b = checkedCast(c, Integer.class);

// This should throw ClassCastException
checkedCast(a, Integer.class);

3 个答案:

答案 0 :(得分:2)

Java类型系统的泛型扩展的一个缺点是,我们如何以单数形式考虑类型并不会扩展到我们如何看待复数类型。

简而言之,通用类型的集合无法安全地投射。构建一个新列表,拉出每个类型并单独检查它,然后返回新列表。如果您忽视此警告,我会指示某人做类似

的事情
List<Customer> customers = new ArrayList<>();
customers.add(new Customer(...));
List<Object> customerObjects = checkCast(customers, Object.class);
customerObjects.add(new Order(...));

你被警告了。

答案 1 :(得分:0)

看看这是否适合您。但是,如果您能够更详细地描述为什么需要这样的方法,人们可以更好地帮助您。

public static
<InputElement, OutputElement extends InputElement,
 InputContainer extends Iterable<InputElement>,
 OutputContainer extends Iterable<OutputElement>>
OutputContainer checkedCast(InputContainer iterable,
                            Class<OutputElement> clazz) {
  @SuppressWarnings("unchecked")
  OutputContainer output = (OutputContainer) iterable;
  return output;
}

答案 2 :(得分:0)

这适用于您的要求 - 除了抛出ClassCastException(如果您真的想要这种行为,您可以自己将它包含在checkedCast方法中):

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
    }

}

更新以匹配新要求: ArrayList xs = checkedCast(new HashSet(),Integer.class) - 不应编译

更新:更新为断言返回的Collection泛型类型扩展了输入Collection的泛型类型。