このJavaコードは、Runnable
インターフェースの実装としてラムダ式を使用してスレッドを生成し、実行しています。私はこのコードにコメントを加えて、どのように動作するのかを説明し、それがなぜ答えD「コンパイルエラーが発生する」になるのかを解説します。
public class Sample { public static void main(String[] args) { int cnt = 0; // メインメソッドのスコープでカウンタ変数cntを宣言して0で初期化 // ラムダ式を使ってRunnableインターフェースの実装を作成 Runnable r = () -> { // ラムダ式の中でcnt変数を再宣言している。これはスコープが異なるためエラーにはならないが、 // このcntは外側のcnt変数とは異なる変数である。 for (cnt = 0; cnt < 10; cnt++) { // このcnt++はループの中でカウンタを増やすために使われているが、 // これが実際にはラムダ式の外側のcnt変数を変更しようとしていることになる。 // Javaのラムダ式では、ラムダ式の外側のローカル変数を変更することは許されていない。 // この行はコンパイルエラーを発生させる。 System.out.println(cnt++); } }; // 新しいスレッドを作成してラムダ式を実行 new Thread(r).start(); }
}
このコードの問題点は、ラムダ式内で外部のローカル変数cnt
を変更しようとしていることです。Javaでは、ラムダ式から参照される外部のローカル変数は実質的にfinal
である必要があります。つまり、ラムダ式内部で変更することはできません。しかし、ここではfor
ループの中でcnt++
というインクリメント演算を行っているため、コンパイルエラーが発生します。
そのため、答えは「D. コンパイルエラーが発生する」となります。
追記
コンパイルエラーを避けるには、ラムダ式内で外部のローカル変数を変更しないようにする必要があります。このコードでは、Runnable
インターフェースの実装内でループ変数cnt
を使用していますが、これが外部スコープの変数cnt
と衝突しています。コンパイルエラーを避けるためには、ラムダ式内で使用するカウンタ変数を独立させる必要があります。
以下はそのための修正案です:
public class Sample { public static void main(String[] args) { // ラムダ式から参照されるローカル変数はfinalまたは実質的finalである必要があるため、 // ラムダ式内で変更する変数はラムダ式内で宣言する。 Runnable r = () -> { for (int i = 0; i < 10; i++) { // ラムダ式内で独立したループカウンタiを使用。 System.out.println(i); } }; // Runnableの実装をThreadコンストラクタに渡してスレッドを起動 new Thread(r).start(); }
}
この変更により、Runnable
の実装内で新しいカウンタ変数i
を導入しました。この変数はRunnable
の実装内でのみスコープされるため、外部の変数に干渉せず、コンパイルエラーが発生しません。また、Runnable
実装外で宣言されたcnt
変数はもはや不要なので、削除することができます。
Discover more from Coursity
Subscribe to get the latest posts sent to your email.