gpt4 book ai didi

java - Consumers 数组中的 ArrayStoreException

转载 作者:行者123 更新时间:2023-12-04 08:46:21 26 4
gpt4 key购买 nike

我正在存储对 BiConsumers<Integer, X> 的引用适应Consumer<Integer> :

public void setConsumer(BiConsumer<Integer, X> consumer) {
fieldConsumer = integer -> consumer.accept(integer, fieldSubject);
}
但我需要其中的 2 个,所以我将代码更改为使用数组:
private Consumer<Integer>[] fieldConsumers;

public MyClass(int numberOfConsumers) {
Consumer<Integer> consumer = integer -> {};
fieldConsumers= (Consumer<Integer>[]) Array.newInstance(consumer.getClass(), numberOfObservers);
}

public void addConsumer(int consumerIndex, BiConsumer<Integer, X> consumer) {
// Offending line
fieldConsumers[consumerIndex] = responseType-> consumer.accept(responseType, fieldSubject);

}
以便可以通过以下方式触发回调:
for (Consumer<Integer> consumer: fieldConsumers) {
consumer.accept(responseType);
}
我得到了错误:
java.lang.ArrayStoreException:
在这条线上:
fieldConsumers[consumerIndex] = responseType-> consumer.accept(responseType, fieldSubject);
现在,如果你还在读这篇文章,我还有一个问题:
如果我这样做,我是否仍然引用外部消费者,而不是使用旧的 fieldConsumers.add(consumer)其中 fieldConsumers 是 List<BiConsumer<Integer, X>> ?

最佳答案

你用过Array.newInstance(consumer.getClass(), numberOfObservers)创建 Consumer<Integer>[]大批。但是consumer.getClass()返回您正在调用方法的对象的实际类,它始终是接口(interface)的实现类。这种元素类型的数组只能保存相同具体类的对象,不能保存接口(interface)的任意实现。
这与例如没有什么不同。

CharSequence cs = "hello";
CharSequence[] array = (CharSequence[]) Array.newInstance(cs.getClass(), 1);
array[0] = new StringBuilder();
在这里, cs类型为 CharSequence并且反射阵列创建似乎创建了 CharSequence[] 类型的阵列, 所以存储一个 StringBuilder应该是可能的。但是自从 cs.getClass()返回实际的实现类 String ,数组实际上是 String[] 类型,因此,尝试存储 StringBuilder产生 ArrayStoreException .
在 lambda 表达式的情况下,事情会稍微复杂一些,因为功能接口(interface)的实际实现类是在运行时提供的,并且有意未指定。您使用了 lambda 表达式 integer -> {}用于在构造函数中创建数组,它评估为与 responseType-> consumer.accept(responseType, fieldSubject) 不同的实现类在 addConsumer 内方法,在这个特定的运行时。
此行为符合 this answer描述最常用环境的行为。尽管如此,其他实现可能会表现出不同的行为,例如对所有 lambda 表达式的特定功能接口(interface)评估为相同的实现类。但也有可能对同一个 lambda 表达式的多次求值产生不同的类。
所以解决方法是使用预期的界面元素类型,例如
fieldConsumers=(Consumer<Integer>[])Array.newInstance(Consumer.class, numberOfObservers);
但是根本不需要创建反射阵列。您可以使用:
fieldConsumers = new Consumer[numberOfObservers];
你不能写 new Consumer<Integer>[numberOfObservers] ,因为不允许创建通用数组。这就是上面的代码使用原始类型的原因。相反,使用反射不会改善这种情况,因为在任何一种情况下它都是未经检查的操作。您可能需要添加 @SuppressWarnings为了它。更清洁的替代方法是使用 List<Consumer<Integer>> ,因为它使您免受数组和泛型的奇怪影响。
不清楚这里的“引用外部消费者”是什么意思。无论哪种情况,您都引用了 Consumer捕获对 BiConsumer 的引用的实现您作为 addConsumer 的参数收到的实现.

关于java - Consumers<X> 数组中的 ArrayStoreException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64295745/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com