質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

50459閲覧

Javaのラムダ式について

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

1クリップ

投稿2016/08/07 11:16

編集2016/08/08 00:10

Javaのラムダ式についての質問です。
ある本に次のように書いていました。
「ラムダ式には「自身が評価され関数の実体が生み出される際、その時点でアクセス可能なすべての変数の情報を記憶し、ラムダ式内で利用できる」という特徴があります。
つまり、次のようなコードが記述可能なのです。

double b = 4.3; IntDoubleFunction fun = x -> x*x*3.14;

ただし、ラムダ式内でラムダ式外にある変数を書き換えることはできません。
また、ラムダ式外にある変数bは内容が変化しない実質的にfinalな変数である必要があります。」

最後の文書「実質的にfinalな変数である必要があります。」についてですが、これってどういう意味なんでしょうか。
次のようなコードを書いてみました。

import java.util.function.IntToDoubleFunction; public class Main { public static void main(String[] args) { int a = new java.util.Random().nextInt(4); IntToDoubleFunction b = x -> {return a*a*3.14;}; double c = b.applyAsDouble(a); System.out.println(c); } }

上のコードの変数aはfinalではなく、実行の度に値が変わりますが、問題なく動作しました。
しかしながら、確かに、一つの実行の時には、値が定まるという意味ではfinalな変数になっているのかもしれませんが、なんとなく腑に落ちない感じです。

「実質的にfinalな変数」とは一体どういう変数なのでしょうか。

Mr_Roboto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

flied_onion

2016/08/07 11:40

コードはコードブロック(```で括る)ようにしてください。選択して </> ボタンでもOKです。
退会済みユーザー

退会済みユーザー

2016/08/08 00:10

すいません、今まで知らずに直で書いていました。以後気をつけます。
guest

回答3

0

int a = new java.util.Random().nextInt(4);

このあとaが書き換わってないので、finalつけてもコンパイルエラーにはならない。

というような状況です。
これが

int a = new java.util.Random().nextInt(4); a = new java.util.Random().nextInt(4); IntToDoubleFunction b = x -> {return a*a*3.14;};

の場合はエラーになると思います。

投稿2016/08/07 11:39

flied_onion

総合スコア2604

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/08 00:04

すいません、その場合も二行目から実質的に変数aはfinalになるのではないでしょうか。
swordone

2016/08/08 00:37

もし最初のaに対してfinalを付けたら、2行目で代入操作を行っているためコンパイルエラーとなります。つまりこのaはfinalとして扱うことができません。
guest

0

ベストアンサー

Javaの言語仕様になりますが、以下の言い回しが使われます。

内部クラスやラムダ式において、その外側で定義されているローカル変数を使う場合は、そのローカル変数に 暗黙にfinalが付いているもの と見なされる。

例えば以下のコードはコンパイルエラーになります。

java

1public void test() { 2 int value = 10; 3 List<Integer> arrays = Arrays.asList(1,2,3,4,5); 4 5 arrays.stream().forEach(element -> { 6 // ローカル変数を変更 - ここでコンパイルエラー 7 value = value +1; 8 }); 9}

コンパイルエラーのメッセージからも「実質final」が表示されますね。

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

特にfinal宣言しなくても、ラムダ式の中からは、メソッド内のローカル変数はfinalで扱う(不変でなければならない)ので、宣言はしてもしなくても扱いは同じになる、の意味です。

投稿2016/08/07 12:33

A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/08 00:05

なるほど、実用的にはローカル変数の書き換えがfinalでない場合に当たるという認識でよろしいでしょうか。
A-pZ

2016/08/08 01:25

"ローカル変数の書き換えがfinalでない場合に当たる" が何を指しているのかがわかりにくいですが…、メソッド内に記述したラムダ式からの中からは、メソッド内のローカル変数を参照できるが、変更するのは言語仕様で許可していないので、結果的にfinalと同じ扱いをします。
guest

0

1回毎の実行では、aは一度設定されたあと変更されません。つまり、finalとして扱って差し支えないというのが「実質的final」の意味です。

投稿2016/08/08 00:37

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問