这是我的问题。我有一个简单的测试代码。
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
的子项。
例如,正确的情况是传递扩展 Command
的 MyCommand
类。
Java 有可能吗?
附言
public abstract class AbstractCommand implements Command {
// ...
}
AbstractCommand 类的解决方案不合适,因为我需要额外检查命令的类型。如果我不这样做,我将在传递 AbstractCommand.class
时得到 InstantiationException
。
最佳答案
您不能使用泛型强制执行此类限制。您可以做的最好的事情是在方法内部进行类型检查,如果接收到 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;
}
更好的方法是向接口(interface)方法添加文档注释,以便任何实现类都知道该契约。
另一种方法,如果在您的情况下可行,可以在 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
的可见性,因为您不会在其他地方使用它。
关于java - 如何防止使用 Java 泛型检查根类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29064985/