这是我的问题。我有一个简单的测试代码。
public interface CommandFactory {
public <T extends Command> T createCommand(Class<T> commandClass);
}
class Test implements CommandFactory {
public static void main(String[] args) {
Test test = new Test();
test.createCommand(Command.class); // not valid case. should stop this action by compiler
}
@Override
public <T extends Command> T createCommand(Class<T> commandClass) {
return commandClass.newInstance();
}
}
如您所见,我传递了根类型
Command
。但是我想防止这种情况。我想要的是仅将createCommand
的子级传递给Command
方法。正确的情况是传递
MyCommand
类,该类扩展了Command
。Java可能吗?
聚苯乙烯
public abstract class AbstractCommand implements Command {
// ...
}
AbstractCommand类的解决方案是不合适的,因为我需要另外检查命令的类型。如果我不这样做,则在传递
InstantiationException
时会得到AbstractCommand.class
。 最佳答案
您不能使用泛型强制执行此类限制。最好的办法是在方法内部进行类型检查,并在收到Command.class
作为参数时引发异常。甚至,为该场景添加文档注释:
/**
*
* @param cl
* @throws IllegalArgumentException
* when type of cl is Command.class
* @return
*/
public <T extends Command> T createCommand(Class<T> cl) {
if (cl == Command.class) {
throw new IllegalArgumentException("Can only accept subclasses of Command");
}
return null;
}
最好将文档注释添加到接口方法,以便任何实现类都知道合同。
如果可行,另一种方法是在
Command
和MyCommand
之间引入一个抽象类,并相应地更改范围:class Command {
}
abstract class AbstractCommand extends Command {
}
class MyCommand extends AbstractCommand {
}
因此,您的所有子命令现在都将扩展
AbstractCommand
而不是Command
。然后,您的界面将类似于:public interface CommandFactory {
public <T extends AbstractCommand> T createCommand(Class<T> cl);
}
然后,您不能将
Command.class
传递给它。但是我认为这不会解决您要解决的具体问题(我们真的不知道这是什么),因为现在您可以将AbstractCommand.class
传递给该方法。但是,您可以使用AbstractCommand
的可见性,因为您不会在其他地方使用它。