Java 在使用两个接口声明泛型类型参数时,如何避免不必要的强制转换

Java 在使用两个接口声明泛型类型参数时,如何避免不必要的强制转换,java,generics,type-safety,Java,Generics,Type Safety,为什么我必须在下面的代码中显式地将命令强制转换为C? 命令实现可运行和可描述 @Test public <C extends Runnable & Describable> void testMapOfCommands() throws Exception { Map<String, C> commands = Maps.newHashMap(); for(Commands command : Commands.values()) {

为什么我必须在下面的代码中显式地将命令强制转换为C? 命令实现可运行和可描述

@Test
public <C extends Runnable & Describable> void testMapOfCommands() throws Exception
{
    Map<String, C> commands = Maps.newHashMap();
    for(Commands command : Commands.values())
    {
        commands.put(command.name(), (C) command);
    }
    //Use commands here (not relevant to my question):
    //CommandLineParser.withCommands(commands).parse("commit");
}

private enum Commands implements Runnable, Describable
{
    commit
    {
        @Override
        public void run()
        {
            System.out.println("COMMIT");
        }

        @Override
        public String description()
        {
            return "Commits something";
        }
    };
}

但是我试图避免引入一个新类型,因为已经有两种类型可用,并且我已经有了一个更复杂的命令类。我在这里抓救命稻草吗?

您拥有的是一个
command
类型的
Commands
对象。但是由于您的泛型类型声明
,Java希望
C
可描述
可运行
,但是
C
不是必需的
命令

这种特殊的测试方法只适用于
命令
,因此它不应该是通用的。这应该起作用:

public void testMapOfCommands() throws Exception
{
    Map<String, Commands> commands = new HashMap<String, Commands>();
    for(Commands command : Commands.values())
    {
        commands.put(command.name(), command);
    }
}
public void testMapOfCommands()引发异常
{
Map commands=newhashmap();
对于(命令:Commands.values())
{
commands.put(command.name(),command);
}
}

首先,请发布整个课程。其次,对于Runnable这样的接口,您需要使用实现,而不是扩展。对代码进行了一些更新,我认为所有相关的代码都发布了。你缺了什么部位?@锑:没有。在泛型类型中,使用extends。不是工具。即使使用接口。给定代码,如果使用命令以外的任何泛型类型调用泛型方法,也会得到ClassCastException。如果我创建一个实现这两个接口的类Foo,并调用
yourObject.testMapOfCommands()
,它将无法工作。我不明白为什么你的方法是泛型的,特别是如果它是一个单元测试方法的话。我试图使用Map,但是在没有声明C的情况下无法让它工作。这是有效的!谢谢不过,如果我能理解为什么编译器不能将命令强制转换为可运行和可描述的,我将不胜感激。我的代码也运行得很好,只是(C)命令有点奇怪。Java编译器认为C可以是同时实现
Runnable
descripable
的任何东西,即使它是
Commands2
,也恰好是
descripable
Runnable
。因此它不允许类型为
Commands
的参数,因为您不应该将
Commands
放入可能是
HashMap
的对象中(即使我们知道它确实不是)。啊,这是因为编译器无法理解我只需要命令的可运行和可描述部分。Java的类型系统真的不够强大,无法处理像这样的“交集类型”。
public void testMapOfCommands() throws Exception
{
    Map<String, Commands> commands = new HashMap<String, Commands>();
    for(Commands command : Commands.values())
    {
        commands.put(command.name(), command);
    }
}