这是我的问题。我有一个简单的测试代码。

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

最好将文档注释添加到接口方法,以便任何实现类都知道合同。

如果可行,另一种方法是在CommandMyCommand之间引入一个抽象类,并相应地更改范围:
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的可见性,因为您不会在其他地方使用它。

10-08 16:06