gpt4 book ai didi

并行类层次结构上下文中的 Java 泛型问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:26:33 24 4
gpt4 key购买 nike

我在设计并行类层次结构时遇到了一些编译器错误。这个问题似乎源于 Java 的限制(与 C++ 不同),Java 没有公共(public)“typedef”来允许从泛型类外部访问类型参数。我想下面的示例代码最能说明我的问题。

public interface Bean { }
public class GreenBean implements Bean { }
public class RedBean implements Bean { }

// All BreanCounter classes implement this interface and interact with their
// corresponding concrete bean classes.
public interface BeanCounter <B extends Bean> {
public void addBean(B bean);
public Collection<B> getBeans();
}

// DefaultBeanCounter implements logic shared by GreenBeanCounter and RedBeanCounter
public class DefaultBeanCounter <B extends Bean> implements BeanCounter<B> {

private List<B> beans = new ArrayList<B>();

@Override
public void addBean(B bean) { beans.add(bean); }

@Override
public Collection<B> getBeans() { return beans; }
}

public class GreenBeanCounter extends DefaultBeanCounter<GreenBean> { }
public class RedBeanCounter extends DefaultBeanCounter<RedBean> { }

使用上述设置,编译器会报错以下代码:

public class BeanCounterMaster <C extends BeanCounter<? extends Bean>> {
public void mergeBeans(C des, C src) {
for (Bean bean : src.getBeans()) {
des.addBean(bean); //compiler error on this line
}
}
}

错误信息如下:

The method addBean(capture#2-of ? extends Bean) in the type BeanCounter is not applicable for the arguments (Bean)

这是可以理解的,但很尴尬,因为 src 和 des 显然是同一类型。然而,我们不能移动他们的 bean,因为我们只能使用基类型“Bean”。在 C++ 世界中,我们可以使用“C::BeanType”来指代具体的 bean 类型。为了解决这个问题,我决定将合并逻辑放入已知 bean 类型的 DefaultBeanCounter 中:

所以我添加了以下方法:

public interface BeanCounter <B extends Bean> {
public void mergeBeans(BeanCounter<B> anotherCounter);
}

public class DefaultBeanCounter <B extends Bean> implements BeanCounter<B> {
@Override
public void mergeBeans(BeanCounter<B> anotherCounter) {
for (B bean : anotherCounter.getBeans())
addBean(bean);
}
}

现在 BeanCounterMaster 看起来像:

public class BeanCounterMaster <C extends BeanCounter<? extends Bean>> {
public void mergeBeans(C des, C src) {
des.mergeBeans(src); // Still got compiler error
}
}

新的编译器错误如下:

The method mergeBeans(BeanCounter) in the type BeanCounter is not applicable for the arguments (C)

我在这里错过了什么?

最佳答案

仅使用 C extends BeanCounter<? extends Bean> 时,您将丢失有关特定类型 bean 的信息。因此,在遍历 src.getBeans() 时你只知道你正在使用 Bean s 和编译器在将它们添加到 des 时无法判断它们应该是“相同类型” .

解决方法是提供 BeanCountMaster两种类型参数:

public class BeanCounterMaster <C extends BeanCounter<B>, B extends Bean> {
public void mergeBeans(C des, C src) {
for (B bean : src.getBeans()) {
des.addBean(bean);
}
}
}

请注意,如果需要,mergeBeans可能只是一个静态的 generic method :

public static <B extends Bean> mergeBeans(
BeanCounter<B> des,
BeanCounter<? extends B> src
) {
for (B bean : src.getBeans()) {
des.addBean(bean);
}
}

这里我去掉了C赞成只服用BeanCounterB ,如果你想考虑的话。注意我还做了 src一个BeanCounter<? extends B> ,这意味着您可以复制例如一个BeanCounter<FrozenGreenBean>进入BeanCounter<GreenBean> (参见 What is PECS (Producer Extends Consumer Super)?)。

关于并行类层次结构上下文中的 Java 泛型问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20559198/

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