簡體   English   中英

如何解決 IntelliJ 突出顯示的未經檢查的轉換問題?

[英]How do I resolve the unchecked cast problem IntelliJ is highlighting?

語境

我正在為我的 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'

這是我需要關心的事情嗎/有沒有辦法解決它(不抑制警告。)

我擔心它突出了我設計中的缺陷。

未經檢查的強制轉換字面意思是 - Java 無法檢查強制轉換是否有效(這是由於類型擦除),因此在強制轉換點不會有ClassCastException ,這通常會使它更難調試。

例如,如果您這樣做:

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 會發現將AnotherTypeOfCommandCommandExecutor<SomeTypeOfCommand>是無效轉換,並在以下行拋出ClassCastException

CommandExecutor<T> executor = (CommandExecutor<T>) executors.get(commandAlias);

然而,轉換實際上是未經檢查的,所以ClassCastException只會在稍后調用SomeTypeOfCommandExecutor.execute時拋出。 此時, Java 可以看到傳入的參數不是SomeTypeOfCommand 這可能會導致混亂的堆棧跟蹤。

這就是警告警告您的內容。 IMO,這沒什么好擔心的,因為executor.execute(command); 在未經檢查的演員表之后不遠(緊接着),所以你基本上是在下一行立即“檢查”演員表。 如果您想更加清楚地知道您正在檢查演員表,您可以在CommandExecutor中添加一個方法,如下所示:

boolean canExecute(Object command);

在實現中,您只需使用instanceof來檢查command

旁注:如果每種類型的命令只能有一個命令執行程序,我建議您使用Class<?>作為地圖的鍵類型。 這樣,在registerdispatch中,你可以要求 class 類型和命令的類型必須相同,這樣可以防止這樣的事情發生:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM