teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

コード解説追加

2017/11/10 19:47

投稿

swordone
swordone

スコア20675

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
+ ```