OCJP Gold SE 8 認定資格試験ポイント解説セミナーに参加しました。

はじめに

タイトルのセミナーを受けてきました。

講義していただいた内容のうち、私にとって目新しかったものをこの記事に残します。

ラムダ式と実質的final(effectively final)

実質的finalとは

Java8では、無名クラスやラムダ式で実質的にfinalな変数にアクセス可能になりました。

実質的にfinalな変数とは、final指定されていないが、final指定してもエラーにならない変数のことを言います。

具体的には以下に示すような場合実質的finalと言います。

具体例

package seminar;

import java.util.Arrays;
import java.util.List;

public class EffectivelyFinalTest {
    private int value = 1;
    
    public void doSomething(int arg1, int arg2) {
        List<Integer> nums = Arrays.asList(1, 2, 3);

        // 1. 実質的final (ローカル変数)
        int effectivelyFinalValue = 10;
        nums.replaceAll(n -> n + effectivelyFinalValue);

        // 2. 実質的finalでない (ローカル変数)
        int notEffectivelyFinalValue = 20;
        notEffectivelyFinalValue += 10;
        // nums.replaceAll(n -> n + notEffectivelyFinalValue); // コンパイルエラー
        
        // 3. 実質的final (引数)
        nums.replaceAll(n -> n + arg1); // これはOK

        // 4. 実質的finalでない (引数)
        arg2 += 1000;
        // nums.replaceAll(n -> n + arg1); // コンパイルエラー
        
        // 5. インスタンス変数
        value += 1;
        nums.replaceAll(n -> n + value); // これはOK(なぜ?)
        
        // 表示
        nums.forEach(System.out::println);
    }
    
    public static void main(String[] args) {
        new EffectivelyFinalTest().doSomething(100, 1000);
    }
}

2.をコメントアウトしないと、以下に示すメッセージが表示されます。

Local variable notEffectivelyFinalValue defined in an enclosing scope must be final or effectively final

出力結果は以下の通りです。

113
114
115

疑問点

  • Java7で実質的finalな変数を無名クラス内で参照しようとするとどうなるか。
  • 実質的finalな変数を無名クラス内から参照できるようにしたのは、特定の引数に対しいつでも同じ値を返すという関数のルールに反しないからだと思う。サンプルソースの5.でインスタンス変数を参照できるのはなぜか。
  • 実質的finalな変数を無名クラス内から参照できるようにし、実質的finalでない変数を無名クラス内から参照できないようにするのはなぜか。

Streamの特徴

【執筆中】

  • データソースのCollectionは変更されない
  • 遅延評価
  • 終端処理の一回性(仮)

さいごに

【執筆中】

補足

  • comparingとthenComparingのちがい

【執筆中】

以上です。