簡體   English   中英

靜態方法參考泛型類型解決方案

[英]Static method reference generic type solution

我知道這種類型的問題已經發布過,但是即使在檢查了所有鏈接之后,我也無法針對我所面臨的問題提出解決方案。 這是我所擁有的以及我想要它做的:

@FunctionalInterface
public interface ProcessExecute {
    <K, T> K executeProcess(T arguments);
}

一個簡單的函數接口(以便可以將其表示為lambda),它帶有一個T參數(意味着可以為其提供不同的參數)和一個K返回類型,這意味着它將返回一個K對象。 接下來,我有這個:

public interface ProcessHandler {

   void initializeMap();

   Process retrieveProcess(String key,Object parameters);

   <K, T> K executeProcess(String key,T parameters);

   <K> K executeProcess(String key);

}

為了使說明有意義,在上述接口的實現中,我有一個HashMap,它將String鍵鏈接到ProcessExecute項。 因此,ProcessHandler應該僅將String作為鍵,在映射中找到它,然后對映射中找到的對象調用ProcessExecute :: executeProcess方法,然后返回需要返回的內容(由參數類型指定) 。 基本上,ProcessHandler中的executeProcess與ProcessExecute中的executeProcess相同。 現在,我為ProcessHandler實現了以下實現:(由於類很大,所以我僅會放一個示例,但就足夠了)

public class ProcessManager implements ProcessHandler {
   private static final Map<String, ProcessExecute> processMap = new HashMap<>();
   private static final ProcessHandler instance = new ProcessManager();

   public static ProcessHandler getInstance() {
      return instance;
   }
   //many other methods identical to executeRam (that return boolean/String/int and take String or other types as arguments
   private static Process executeRam(Void arguments) {
      Process ram = null;
      try {
          ram = new ProcessBuilder("free", "m").start();
      } catch (IOException e) {
          Log.printLog(TAG.ERROR, "Unable to run free -m command!");
      }
      return ram;
  }

  @Override
  public void initializeMap() {
  //many other declarations identical to this one
    ProcessExecute ramMonitor =ProcessManager::executeRam;
    processMap.put("ram", ramMonitor);
  }

  @Override
  public Process retrieveProcess(String key, Object arguments) {
      return (Process) processMap.get(key).executeProcess(arguments);
 }


  @Override
  public <K, T> K executeProcess(String key, T parameters) {
      return processMap.get(key).executeProcess(parameters);
  }

  @Override
  public <K> K executeProcess(String key) {
      return processMap.get(key).executeProcess(null);
  }

}

問題是在initializeMap()方法中進行編譯時:將項目聲明為

ProcessExecute xxx = ProcessManager:executeXXX;

它報告方法引用中的錯誤返回類型:無法將java.lang.Process轉換為K (這特定於executeRam方法,但是它擴展到了所有其他方法,例如,不能轉換java.lang.String等等)。

我究竟做錯了什么? 需要更改哪些內容才能進行編譯? 為了澄清我想要在該類中做什么,我想要在ProcessManager中調用executeProcess(String key,T parameters)時,要它在HashMap中搜索該鍵,然后執行該項目的(即ProcessExecute) executeProcess方法及其正確推斷類型的方法(因為許多方法返回null或boolean或Strings或Integers並以不同的類型作為參數,如上所述),而且對於我來說,我不知道在哪里我的邏輯是錯。

更令我困惑的是,我設法找到了這個問題的(怪異?)解決方案,但是由於我根本不理解它為什么起作用,所以我不想實施它,所以如果可以的話,請幫我一下請說明以下原因,以及如何改進或更改它。 基本上,如果我將executeRam方法更改為此:

private static <K, T> K executeRam(T arguments) {
  Process ram = null;
  try {
      ram = new ProcessBuilder("free","m").start();
  } catch (IOException e){
      Log.printLog(TAG.ERROR,"Unable to run free -m command!");
  }
  return (K) ram;
}

然后,它將不會在initializeMap()方法中給出任何錯誤(並且它實際上可以工作)。 但是將返回值強制轉換為K(?)似乎有點怪異和怪異。 此外,更改所有其他方法的解決方案也不完整:在我的具有原始返回類型(例如boolean)的方法上,它將抱怨無法將boolean強制轉換為K,因此我無法將我的解決方案適應其他方法。

您在這里遇到的問題是要在方法上聲明類型變量。

public interface ProcessExecute {
    <K, T> K executeProcess(T arguments);
}

意味着您可以將任何內容傳遞給該方法,並期望返回任何類型。

ProcessExecute pex = ...;
String s = pex.executeProcess(1);
Integer i = pex.executeProcess("");

除非您將結果用作Object (如Object obj = pex.execute(""); ),或者從該方法返回null ,否則在調用它時將導致ClassCastException

代替:

public interface ProcessExecute<K, T> {
    K executeProcess(T arguments);
}

意味着,在給定ProcessExecute實例的情況下,您始終必須傳遞相同的參數類型,並且始終將返回相同的參數。

然后,您可以使用如下所示的實例:

ProcessExecute<Void, Process> ramMonitor = ProcessManager::executeRam;
Process p = ramMonitor.executeProcess(null);

暫無
暫無

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

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