Java 泛型:筛选集合<;T>;但同时也限制了它的随机访问
假设我想要这样一种方法:Java 泛型:筛选集合<;T>;但同时也限制了它的随机访问,java,generics,type-inference,Java,Generics,Type Inference,假设我想要这样一种方法: private static <T> Collection<T> filter(Collection<T> initial, Predicate<T> predicate){ //.... } 这对声明有效,但对调用方无效。即: filter(List.of(1,2,3), x -> x > 1); // fails 我觉得有点尴尬的是,如果我删除&RandomAccess部分,编译(以及T的解析)
private static <T> Collection<T> filter(Collection<T> initial, Predicate<T> predicate){
//....
}
这对声明有效,但对调用方无效。即:
filter(List.of(1,2,3), x -> x > 1); // fails
我觉得有点尴尬的是,如果我删除&RandomAccess
部分,编译(以及T
的解析)会起作用:
private static <T, M extends Collection<T>> Collection<T> filter(M initial, Predicate<T> predicate){
....
}
私有静态集合筛选器(M初始值,谓词){
....
}
如果RandomAccess
采用类型参数,我会理解是否会发生故障。但是它没有,所以(至少在我的理解中)它不应该影响T
的分辨率
有没有一种方法可以有这样的编译时约束
如果RandomAccess使用类型参数,我会理解是否会发生故障。但是它没有,所以(至少在我的理解中)它不应该影响T的分辨率
事实并非如此。过滤器的问题(列表(1,2,3),x->x>1)
表示表达式的静态类型列表。of(1,2,3)
不是RandomAccess
的子类型,该表达式被拒绝,因为它不满足扩展RandomAccess
约束
以下两种方法都可以毫无问题地编译,T
的推断不受影响
filter(new ArrayList<>(List.of(1, 2, 3)), x -> x > 1);
filter(new ArrayList<>(List.of("a", "b", "c")), x -> x.length() > 1);
filter(新的数组列表(1,2,3的列表)),x->x>1;
过滤器(新的数组列表(“a”、“b”、“c”)的列表),x->x.length()>1;
因为
ArrayList
既是集合
又是随机访问
子类型。然而,我猜想,根据编译器实现的不同,您可能会遇到多种类型的无用错误消息(例如,类型Main中的方法过滤器(M,谓词)不适用于过滤器(…)上的参数(List)
和类型不匹配:列表(…)上的无法从List转换为M
在Eclipse中)过滤器((收集和随机访问)列表(1,2,3),x->x>1)代码>有效,仅供参考。@Eugene well。。。尝试filter((Collection&RandomAccess)新建链接列表(Arrays.asList(1,2,3)),x->x>1)
。该强制转换之所以有效,是因为List.of(1,2,3)
返回RandomAccess
类型。由于Java在编译时没有检查对交互类型的强制转换(在类似的情况下),所以不会出现编译时错误,而是在运行时出现类强制转换异常。对,我知道并理解这一点,但同时:System.out.println(List.of(1,2,3)instanceof RandomAccess);//是的,所以我真的不明白“…是表达式列表的静态类型。of(1,2,3)不是RandomAccess的子类型”:|@Eugene,List.of(…)
的返回类型是List
。而且在List
的类型层次结构中没有编译器会知道的RandomAccess
(List->Collection->Iterable
)。如您所知,泛型边界是在编译时强制执行的(除非使用原始类型),这是基于静态类型的。而new ArrayList()
和List.of()
这两种方法都有效,因为它们返回RandomAccess的实例(
java.util.ArrayList`和java.util.ImmutableCollections.ListN
do实现RandomAccess
)
filter(new ArrayList<>(List.of(1, 2, 3)), x -> x > 1);
filter(new ArrayList<>(List.of("a", "b", "c")), x -> x.length() > 1);