2017-06-19 77 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

@阿德里安 - 谢谢。 –