[英]java stream return array of parameterized class
Situation: 情况:
public class P {
public static Predicate<Double> isEqual(double value) {
return p -> (Math.abs(p - value) <= 0.000001);
}
}
public class Entity {
private double[] values;
public double getValue(int index) {
return values[index];
}
}
Code with unchecked conversion: 未经检查的转化代码:
public Attribute split(Entity[] examples) {
@SuppressWarnings("unchecked")
Predicate<Double>[] pa = Arrays.stream(examples).map(e -> P.isEqual(e.getValue(a.index))).toArray(Predicate[]::new);
return ...;
}
How can solve this without unchecked conversion? 没有未经检查的转换怎么解决这个问题?
I can't use such: 我不能用这样的:
public Attribute split(Entity[] examples) {
Predicate<Double>[] pa = Arrays.stream(examples).map(e -> P.isEqual(e.getValue(a.index))).toArray(Predicate<Double>[]::new);
return ...;
}
I'm actually going to make my comments an answer because I found this interesting to research and I'm now pretty confident. 我实际上是要把我的评论作为答案,因为我发现这对研究很有意思,我现在非常自信。 The answer hinges on the fact (as @azurefrog noted) that creating generic arrays must have an unchecked conversion. 答案取决于事实(正如@azurefrog所说),创建通用数组必须具有未经检查的转换。
See: How to create a generic array in Java? 请参阅: 如何在Java中创建通用数组?
Predicate<Double>[]::new
would be equivalent to Predicate<Double>[]::new
相当于
IntFunction<Predicate<Double> []> predicateArrayMaker = (int size) -> new Predicate<Double>[size];
However, you cannot create a generic array without an unchecked conversion. 但是,如果没有未经检查的转换,则无法创建通用数组。 For example, 例如,
Predicate<Double>[] predicateArray = new Predicate<Double>[10];
will have the same problem. 会有同样的问题。
So, the unchecked conversion must necessarily happen as explained in the linked answer. 因此,未经检查的转换必须按照链接的答案中的说明进行。
There is no way to create a generic array without unchecked conversion, as the creation of a generic array is an unsafe operation per se. 没有未经检查的转换就无法创建通用数组,因为创建通用数组本身就是一种不安全的操作。 Since its creation is not allowed, you can only create a non-generic array and perform an unchecked conversion. 由于不允许创建,因此您只能创建非泛型数组并执行未经检查的转换。
Simply said, every operation that could enable subsequent heap pollution without any warning, must be considered an unsafe operation that either, generates a warning itself or even will produce an error. 简单地说,每一个可以在没有任何警告的情况下实现后续堆污染的操作,都必须被认为是一种不安全的操作,要么自身产生警告,要么甚至会产生错误。 The problem can easily demonstrated: 问题很容易证明:
Predicate<Double>[] p=/* someway to get the array*/;
Object[] array=p;
array[0]=(Predicate<Integer>)i -> i==0;
This situation, where an array whose elements are declared to be of type Predicate<Double>
, but one of them is actually a Predicate<Integer>
, is called heap pollution . 这种情况,其中一个数组的元素被声明为Predicate<Double>
类型,但其中一个实际上是Predicate<Integer>
,被称为堆污染 。 Since both, the assignment of p
to a variable of type Object[]
and the assignment of a Predicate<Integer>
to an element of an array of type Object[]
, are legal constructs that don't generate warnings, the creation of the array itself must be considered an unsafe operation that must generate either, a warning or an error, to prevent the subsequent silent heap pollution. 既然两者都将p
赋值给Object[]
类型的变量,并将Predicate<Integer>
赋值给Object[]
类型的数组元素,则是不生成警告的合法构造,创建数组本身必须被视为不安全的操作,必须生成警告或错误,以防止随后的静默堆污染。 Otherwise, Generics could not claim to provide compile-time safety, ie that code free of unchecked/unsafe operations guarantees the absence of heap pollution. 否则,泛型无法声称提供编译时安全性,即没有未经检查/不安全操作的代码可确保不存在堆污染。
The only exception where generic array creation is accepted, is in the context of varargs, but to have a warning free code, ie using @SafeVarargs
, you have to accept fundamental restrictions, eg you can not assign the array to any other variable nor return it from the method, to avoid a sneaky introduction of the problem described above. 接受通用数组创建的唯一例外是在varargs的上下文中,但是为了获得无警告代码,即使用@SafeVarargs
,您必须接受基本限制,例如,您不能将数组分配给任何其他变量也不能返回它从方法,避免偷偷摸摸地引入上述问题。
So the bottom line is, either, you accept that there is an unchecked operation or you use a List
and “use a List
” means use a List
, not try to create the array via a List
. 所以底线是,你接受有一个未经检查的操作或你使用List
和“使用List
”意味着使用 List
,而不是尝试通过List
创建数组。 The fundamental difference between a List
and an array is that you can't assign a List<Predicate<Double>>
to a List<Predicate>
nor List<Object>
(without an unchecked operation), so it provides the safety that Generics promise. List
和数组之间的根本区别在于,您不能将List<Predicate<Double>>
分配给List<Predicate>
或List<Object>
(没有未经检查的操作),因此它提供了Generics承诺的安全性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.