回答編集履歴
1
コード解説追加
answer
CHANGED
@@ -2,9 +2,37 @@
|
|
2
2
|
Collections.sortメソッドの引数は(List<T>, Comparator<? super T>)となっています。このlistの部分にList<Element>が渡っているので、Comparatorの型もElementかその親クラスのものである必要があると推測してくれるのです。
|
3
3
|
|
4
4
|
Comparator.comparingIntはComparator<T>を返す**staticメソッド**です。このメソッドを渡すと、このTの部分をElementであるとしてコンパイルしてくれるのです。このため、2はコンパイルが通ります。
|
5
|
+
```java
|
6
|
+
// Comparator.comparingIntの総称型を自動でElementと推定
|
7
|
+
Collections.sort(list, Comparator.comparingInt(e -> e.n1));
|
8
|
+
```
|
5
9
|
|
6
10
|
一方、つないで書いているthenComparingIntメソッドはComparatorの**defaultメソッド**で、Comparator<T>のオブジェクトに使うことでComparator<T>を返すインスタンスメソッドのような役割です。
|
7
11
|
3のComparatorの書き方の場合、最初のcomparingIntメソッドの時点で型を推測する根拠が何もないため、TをObjectとして扱います。これにthenComparingIntメソッドを使うため、TがObjectのままとなります。
|
8
12
|
つまり、comparingIntやthenComparingIntに渡しているラムダ式のeがObjectとして扱われ、Objectクラスにn1,n2,n3というフィールドがないため、ご質問のエラーが出ます。
|
13
|
+
```java
|
14
|
+
// この段階では型推論が効かないため、comparingIntの総称型はObject扱い
|
15
|
+
// つまり、ラムダ式はToIntFunction<Object>で、eの型がObject扱い
|
16
|
+
Collections.sort(list, Comparator.comparingInt(e -> e.n1)
|
17
|
+
// これ以降はComparator<Object>に対してthencomparingIntを呼んでいるため、
|
18
|
+
// 引数ラムダ式はToIntFunction<Object>
|
19
|
+
.thenComparingInt(e -> e.n2)
|
20
|
+
.thenComparingInt(e -> e.n3));
|
21
|
+
```
|
9
22
|
|
10
|
-
この問題は、comparingIntにおけるTがElementとわかれば解決します。そのため、総称型を明示的に指定する(4の方法)か、ラムダ式の引数、つまりFunctionの型を明示する(5の方法)ことでコンパイルが通るようになるのです。
|
23
|
+
この問題は、comparingIntにおけるTがElementとわかれば解決します。そのため、総称型を明示的に指定する(4の方法)か、ラムダ式の引数、つまりFunctionの型を明示する(5の方法)ことでコンパイルが通るようになるのです。
|
24
|
+
```java
|
25
|
+
// comparingIntの総称型を明示的にElementにすることで、引数ラムダ式をToIntFunction<Element>と推定
|
26
|
+
Collections.sort(list, Comparator.<Element>comparingInt(e -> e.n1)
|
27
|
+
// 以降もComparator<Element>に対するメソッドのため、Elementに対する操作とわかる
|
28
|
+
.thenComparingInt(e -> e.n2)
|
29
|
+
.thenComparingInt(e -> e.n3));
|
30
|
+
```
|
31
|
+
```java
|
32
|
+
// ラムダ式の引数型をElementと明示することて、このラムダ式がToIntFunction<Element>に確定。
|
33
|
+
// これにより、comparingIntの総称型もElementに確定できる。
|
34
|
+
Collections.sort(list, Comparator.comparingInt((Element e) -> e.n1)
|
35
|
+
// 以下、先述通り
|
36
|
+
.thenComparingInt(e -> e.n2)
|
37
|
+
.thenComparingInt(e -> e.n3));
|
38
|
+
```
|