错误:类型参数枚举不在类型变量 T 的范围内



我对这段代码有问题。当我想插入到地图枚举元素消费者中时,它无法编译并显示错误error: type argument Enum is not within bounds of type-variable T.问题是我无法更改*值类。有没有办法让它工作?

import java.util.*;
import java.util.function.*;
public class Main {
public static void main(String[] args) {}

private static final Map<Class<?>, Consumer<Element>> CONFIG_ELEMENTS = new HashMap<>();
static {
CONFIG_ELEMENTS.put(BooleanValue.class, element -> new BooleanElement((ConfigElement<Boolean, BooleanValue>) element));
// CONFIG_ELEMENTS.put(EnumValue.class, element -> new EnumElement<>((ConfigElement<Enum, EnumValue<Enum>>) element)); // doesn't compile
}


private static class ConfigValue<T>{}

private static class BooleanValue extends ConfigValue<Boolean> {}

private static class EnumValue<T extends Enum<T>> extends ConfigValue<T> {}


private static class Element{}

private static class ConfigElement<S, T extends ConfigValue<S>> extends Element {}

private static class BooleanElement extends ConfigElement<Boolean, BooleanValue> {
BooleanElement(ConfigElement<Boolean, BooleanValue> value) {}
}

private static class EnumElement<T extends Enum<T>> extends ConfigElement<T, ConfigValue<T>> {
EnumElement(ConfigElement<T, ConfigValue<T>> value) {}
}
}

...有没有办法让它工作?...

我让你的例子以这种方式工作

  1. public <V, U extends ConfigValue<V>>EnumElement(ConfigElement<V, U>value){}…
  2. …new EnumElement((ConfigElement<? extends Enum<?>, EnumValue<? extends Enum<?>>>) element )…

我在几个类中添加了一些骨架实现,以确认该解决方案是可用的:

…
static public void main( String ...args ){

EnumValue< Foo > ev = new EnumValue< >( );

ConfigElement< Foo, EnumValue< Foo > > ce = new ConfigElement< >( );

EnumElement< Foo > ee = new EnumElement< >( ce );

ee.setE( Foo.BAR );

Foo bar = ee.getE( );

out.println( bar );

Consumer< Element > c = CONFIG_ELEMENTS.get( ev.getClass( ) );

c.accept(ee);
}
…

如果要检查它是否为您编译和运行,请单击上面链接中联机 IDE 项目顶部的绿色">开始"按钮。

首先,让我们澄清几件事。你的第一个CONFIG_ELEMENTS.put...相当于(只要确保你理解这一点(。

CONFIG_ELEMENTS.put(
BooleanValue.class,
element -> {
new BooleanElement((ConfigElement<Boolean, BooleanValue>) element);
return;
}
);

现在您声明的CONFIG_ELEMENTS映射知道它所持有的值是类型Element,即上述内容可以写为:

CONFIG_ELEMENTS.put(
BooleanValue.class,
(Element element) -> {
new BooleanElement((ConfigElement<Boolean, BooleanValue>) element);
return;
}
);

这就是为什么完成这项工作的唯一方法是投射该element;因为它的类型是Element,但是你的BooleanElement接受ConfigElement作为输入。这应该是显而易见的。


第二个CONFIG_ELEMENTS.put...解释必须从这个开始:

private static class EnumElement<T extends Enum<T>> extends ConfigElement<T, ConfigValue<T>> {
EnumElement(ConfigElement<T, ? extends ConfigValue<T>> value) {
}
}

请注意? extends ConfigValue<T>> value部分。你需要它,因为泛型是不变的,所以为了能够传递扩展ConfigValue的东西,你需要正确声明参数类型。

其余的解释是我纯粹有根据的猜测,因为我并不真正理解这里发生了什么(我有一些暗示,这与使用原始类型以及来自EnumElementT和来自EnumValueT是不同的类型变量这一事实有关(......

IMO使这项工作最简单的方法是更改以下内容:

private static class EnumValue<T extends Enum> extends ConfigValue<T> {}

使用原始Enum

编辑

这是评论中要求的完整示例:

public class DeleteMe {

private static final Map<Class<?>, Consumer<Element>> CONFIG_ELEMENTS = new HashMap<>();
static {
CONFIG_ELEMENTS.put(BooleanValue.class, element -> new BooleanElement((ConfigElement<Boolean, BooleanValue>) element));
CONFIG_ELEMENTS.put(EnumValue.class,
element -> new EnumElement<>((ConfigElement<Enum, EnumValue<Enum>>) element)); // doesn't compile
}

private static class BooleanValue extends ConfigValue<Boolean> {}
private static class BooleanElement extends ConfigElement<Boolean, BooleanValue> {
BooleanElement(ConfigElement<Boolean, BooleanValue> value) {}
}
private static class ConfigValue<T> {
}
private static class EnumValue<TT extends Enum> extends ConfigValue<TT> {}

private static class Element {}
private static class ConfigElement<S, T extends ConfigValue<S>> extends Element {}

static class EnumElement<T extends Enum<T>> extends ConfigElement<T, ConfigValue<T>> {
EnumElement(ConfigElement<T, ? extends ConfigValue<T>> value) {
}
private T e;

public void setE(T e) { this.e = e; }
public T getE() { return e; }
}

static public void main(String... args) {
EnumValue<Foo> ev = new EnumValue<>();
ConfigElement<Foo, EnumValue<Foo>> ce = new ConfigElement<>();
EnumElement<Foo> ee = new EnumElement<>(ce);
ee.setE(Foo.BAR);
Foo bar = ee.getE();
System.out.println(bar);
Consumer<Element> c = CONFIG_ELEMENTS.get(ev.getClass());
c.accept(ee);
}
enum Foo {
BAR
}
}

最新更新