2013-04-23 78 views
2

为什么我必须在下面的代码中显式地将命令转换为C? 命令实现Runnable和Describable。如何在使用两个接口声明泛型类型参数时避免不必要的强制转换

@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"; 
     } 
    }; 
} 

一个解决办法我心目中是介绍的ICommand扩展双方的Runnable和可描述的:

public interface ICommand extends Runnable, Describable{} 

,但我想避免引入一个新的类型时,已经有两种类型随时可用,我已经有了一个更复杂一点的Command类。我在这里抓秸秆吗?

+0

他们是接口 – jontejj 2013-04-23 22:03:56

+0

首先,请发布整个班级。其次,你需要使用实现,而不是扩展,像Runnable这样的接口。 – Antimony 2013-04-23 22:04:39

+0

更新了一下代码,我认为所有相关代码都已发布。你错过了哪些部分? – jontejj 2013-04-23 22:07:09

回答

6

什么是command对象是Commands类型。但是由于您的泛型类型声明<C extends Runnable & Describable>,Java期望C既是Describable也是Runnable,但C不是必需的Commands

这个特殊的测试方法并不是用于除Commands以外的任何其他工作,所以它不应该是通用的。这应该工作:

public void testMapOfCommands() throws Exception 
{ 
    Map<String, Commands> commands = new HashMap<String, Commands>(); 
    for(Commands command : Commands.values()) 
    { 
     commands.put(command.name(), command); 
    } 
} 
+0

+1。正是我的评论:-) – 2013-04-23 22:12:15

+0

这工作!谢谢。不过,如果我能理解为什么编译器不能将命令转换为Runnable&Describable,我将不胜感激。我的代码工作得很好,只是(C)命令强制转换有点奇怪。 – jontejj 2013-04-23 22:17:18

+0

Java编译器认为C可以是_anything_,它既实现'Runnable'又实现'Describable',即使它是一个'Commands2',恰好也是'Describable'和'Runnable'。所以它不允许'Commands'类型的参数,因为你不应该把'Commands'放到可能是'HashMap '的东西里(即使我们知道它真的不是)。 – rgettman 2013-04-23 22:20:28

相关问题