[英]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.