2017-06-19 78 views
3

我在generics上工作,發現下面的代碼給編譯時錯誤comparing method。在這條線 泛型和比較器

多個標記 - 無法推斷類型參數(個),比較(功能) - A型沒有定義M1(對象)是適用於此處

class A<T> { 
    String m1() { 
     return null; 
    } 
} 

class B { 
    void test() { 
     Comparator<A<String>> target = Comparator.comparing(A::m1).thenComparing(A::m1); 
    } 
} 

有人能幫我理解這種行爲嗎?我該如何解決這個問題?

+0

@ GhostCat--哈哈哈......知道了。它的語言讓我看不起。反正不是質疑我的語言,請檢查你的答案是不正確的。 –

+0

哪個答案;-) ...我希望你已經檢查了我在那裏的鏈接;因爲那對你來說確實是一個有趣的讀物。除此之外:請注意,在我繼續確保您理解我爲什麼做出這一改變之前,我先**改進了您的問題中的措詞。 – GhostCat

回答

7

如果在comparing方法指定確切的泛型類型,代碼編譯。

Comparator<A<String>> target = 
    Comparator.<A<String>, String>comparing(A::m1).thenComparing(A::m1); 
0
Comparator<A<String>> target = Comparator.comparing(A::m1).thenComparing(A::m1); 

thenComparing()需要一個Comparator對象作爲參數...

+1

'thenComparing'有3個重載的方法,其中兩個採用'Function' – Andrew

1

可以嵌套爲

Comparator<A<String>> target1 = Comparator.comparing(A::m1); 
Comparator<A<String>> target2 = target1.thenComparing(A::m1); 


myVarList.sort(target2); 
2

我檢查,發現這裏的問題是,當javac的評估這條產業鏈:

Comparator.comparing(A::m1).thenComparing(A::m1) 

鏈中的最外面的呼叫:

Comparator.comparing(A::m1) 

has no ta rget類型。這是正常的,目標類型只能在鏈條的最裏面調用。因此,當評估方法參考時,javac唯一知道的是目標是一些T.

這意味着javac必須首先推斷T,然後才能嘗試鍵入檢查方法引用 - 這是因爲該方法引用「不精確」

+0

嘿,你可以發佈你的解釋來源嗎? – prsvr

5

你應該爲A級。

Comparator<A<String>> target = Comparator.comparing(A<String>::m1).thenComparing(A<String>::m1); 
2

有趣的問題指定類型參數。還沒有進入JLS,但我猜類型推理在鏈式方法調用的情況下不起作用。 (你可以看到它適用於簡單的Comparator<A<String>> target = Comparator.comparing(A<String>::m1);

一個速戰速決,這是類似的另一種答案,是幫助Java做的類型推斷:

Comparator<A<String>> target = Comparator.comparing(A<String>::m1) 
             .thenComparing(A::m1); 

請注意:在第一種方法做它已經做的伎倆。

(期待,看看是否有人能夠挖掘出JLS,看看這樣的推斷應該是有效的:P)

+0

@阿德里安 - 謝謝。 –