語境
我正在為我的 CQRS 應用程式構建一個命令調度程式。
相關代碼
命令界面
public interface Command {
}
命令執行器介面
public interface CommandExecutor<T extends Command> {
Mono<CommandResult> execute(T command);
}
命令調度器
public class CommandDispatcher {
private final Map<String, CommandExecutor<? extends Command>> executors = new HashMap<>();
// Example usage
public static void main(String[] args) {
CommandDispatcher dispatcher = new CommandDispatcher();
dispatcher.register(MakeRequestCommand.class.getName(), new MakeRequestCommandExecutor());
dispatcher
.dispatch(MakeRequestCommand.class.getSimpleName(), new MakeRequestCommand("Any iPhone"))
.subscribe(System.out::println);
}
public <T extends Command> void register(String commandAlias, CommandExecutor<T> executor) {
executors.put(commandAlias, executor);
}
public <T extends Command> Mono<CommandResult> dispatch(String commandAlias, T command) {
if (!executors.containsKey(commandAlias)) {
throw new RuntimeException("No executor registered for command %s".formatted(commandAlias));
}
CommandExecutor<T> executor = (CommandExecutor<T>) executors.get(commandAlias);
return executor.execute(command);
}
}
問題
以下行在 IntelliJ 中產生警告。
CommandExecutor<T> executor = (CommandExecutor<T>) executors.get(commandAlias);
未經檢查的演員表:'io.freesale.application.command.CommandExecutor<capture<? 將 io.freesale.application.command.Command>>' 擴展為 'io.freesale.application.command.CommandExecutor'
這是我需要擔心的事情嗎/有沒有辦法解決它(不抑制警告??。)
我擔心它會突出我的設計中的缺陷。
uj5u.com熱心網友回復:
未經檢查的強制轉換的字面意思是 - Java 無法檢查強制轉換是否有效(這是由于型別擦除造成的),因此在強制轉換的位置不會有ClassCastExceptions,這通常會使除錯變得更加困難.
例如,如果您這樣做:
dispatcher.register(SomeTypeOfCommand.class.getName(), new SomeTypeOfCommandExecutor());
dispatcher
// we're getting the SomeTypeOfCommandExecutor, but giving it AnotherTypeOfCommand
.dispatch(SomeTypeOfCommand.class.getName(), new AnotherTypeOfCommand())
.subscribe(System.out::println);
SomeTypeOfCommandExecutor是一個CommandExecutor<SomeTypeOfCommand>。如果檢查了強制轉換,Java 會看到強制AnotherTypeOfCommand轉換CommandExecutor<SomeTypeOfCommand>為無效的強制轉換,并ClassCastException在該行拋出一個:
CommandExecutor<T> executor = (CommandExecutor<T>) executors.get(commandAlias);
然而,演員表實際上是未經檢查的,所以 aClassCastException只會在稍后SomeTypeOfCommandExecutor.execute被呼叫時被拋出。此時,Java 可以看到傳入的引數不是SomeTypeOfCommand. 這可能會導致堆疊跟蹤混亂。
這就是警告警告您的內容。IMO,這沒什么好擔心的,因為executor.execute(command);在未經檢查的演員之后不太遠(它是緊隨其后),所以無論如何你基本上是在下一行立即“檢查”演員。如果你想更清楚你正在檢查演員表,你可以添加一個方法CommandExecutor,看起來像:
boolean canExecute(Object command);
在實作中,您只需使用instanceof檢查command.
旁注:Class<?>如果每種型別的命令只能有一個命令執行器,我建議您使用 a作為映射的鍵型別。這樣,在registerand 中dispatch,您可以要求型別別和命令的型別必須相同,這樣可以防止出現以下情況:
.dispatch(SomeTypeOfCommand.class, new AnotherTypeOfCommand())
你會這樣做:
private final Map<Class<? extends Command>, CommandExecutor<? extends Command>> executors = new HashMap<>();
public <T extends Command> void register(Class<T> commandAlias, CommandExecutor<T> executor) {
executors.put(commandAlias, executor);
}
public <T extends Command> Mono<CommandResult> dispatch(Class<T> commandAlias, T command) {
CommandExecutor<T> executor = (CommandExecutor<T>) executors.get(commandAlias);
if (executor == null) {
throw new RuntimeException("No executor registered for command %s".formatted(commandAlias));
}
return executor.execute(command);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/311193.html
上一篇:如何對泛型Kotlin函式的函式引數的引數和回傳值施加泛型約束?
下一篇:打字稿編譯器不強制執行泛型
