我对这段代码有问题。当我想插入到地图枚举元素消费者中时,它无法编译并显示错误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) {}
}
}
...有没有办法让它工作?...
我让你的例子以这种方式工作:
-
public <V, U extends ConfigValue<V>>EnumElement(ConfigElement<V, U>value){}…
-
…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
的东西,你需要正确声明参数类型。
其余的解释是我纯粹有根据的猜测,因为我并不真正理解这里发生了什么(我有一些暗示,这与使用原始类型以及来自EnumElement
的T
和来自EnumValue
的T
是不同的类型变量这一事实有关(......
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
}
}