![](/img/trans.png)
[英]Java Generic error in compilation time: “type argument is not within bounds of type-variable T”
[英]error: type argument Enum is not within bounds of type-variable T
我对这段代码有疑问。 当我想插入 Map EnumElement 消费者时,它无法编译并出现错误error: type argument Enum is not within bounds of type-variable T
。 问题是我无法更改 *Value 类。 有没有办法让它工作?
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) {}
}
}
我在您的几个类中添加了一些骨架实现,以确认该解决方案可用:
…
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
map 知道它持有的值是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
? extends ConfigValue<T>> value
部分。 你需要它,因为generics 是不变的,所以为了能够传递扩展ConfigValue
的东西,你需要正确声明参数类型。
解释的 rest 是我纯粹的有根据的猜测,因为我并不真正理解这里发生了什么(我有一些提示,这与使用原始类型有关,并且来自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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.