lambdaについて調べてみた その4
【前提条件】
[参考資料]
Oracle公式ドキュメント
Lambda Expressions (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
Method References (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
徹底解説!Project Lambdaのすべて returns[Java8Launch]@bitter_foxさん
徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]
【概要】
今回はラムダ内での変数の扱いについてです。
スコープの扱いが匿名クラスとは違うとのことなので、
違いもあわせて調べてみました。
【変数の参照】
メソッドのパラメータ、ローカル変数、ラムダのパラメータの
参照について見てみます。
public class Sample { public static void main(final String[] args) { executeSampleLambda01("method arg"); } private static void executeSampleLambda01(final String param) { String variableValue = "varVal"; final Consumer<String> consumer = lambdaParam -> { System.out.println(param); System.out.println(variableValue); //variableValue = "varVal2"; エラー System.out.println(lambdaParam); }; //variableValue = "varVal2"; エラー consumer.accept("Test"); } }
メソッドパラメータ(param)、ローカル変数(variableValue)、
ラムダのパラメータ(lambdaParam)は参照することができます。
ラムダ内で参照している変数は変更することはできません。
変更するコードを書くとエラーになります。
ここは匿名クラスと同じっぽいです。
[実行結果]
method arg varVal Test
【同名の変数】
同名の変数があった場合の扱いです。
public class Sample { public static void main(final String[] args) { final String methodArg = "method arg"; executeSampleLambda02(methodArg); executeInnerClass02(methodArg); } private static void executeSampleLambda02(final String param) { final Consumer<String> consumer = lambdaParam -> { //final Consumer<String> consumer = param -> { ラムダ引数paramはエラー System.out.println(lambdaParam); }; consumer.accept("Test"); } private static void executeInnerClass02(final String param) { final Consumer<String> consumer = new Consumer<String>() { @Override public void accept(final String param) { System.out.println(param); } }; consumer.accept("Test"); } }
ラムダの場合、パラメータとラムダ外で定義した変数の
名前がかぶっている場合はエラーになります。
匿名クラスの場合、匿名クラス内のメソッドの
パラメータが優先されるのでエラーになりません。
【thisの扱い】
最後にラムダ・匿名クラス内でのthisの扱いについてです。
public class Sample { public static void main(final String[] args) { final Sample sample = new Sample(); sample.executeSampleLambda03(); sample.executeInnerClass03(); } private void executeSampleLambda03() { final Runnable runnable = () -> { System.out.println(this.getClass().getName()); }; runnable.run(); } private void executeInnerClass03() { final Runnable runnable = new Runnable() { @Override public void run() { System.out.println(this.getClass().getName()); } }; runnable.run(); } }
thisは問題なく参照できます。
【いろいろ書いたけど】
ラムダの変数の扱いと匿名クラスでのスコープの違いを調べてみました。
ラムダ内では受け取ったパラメータのみを扱うようにした方が
シンプルで混乱もなくて良いと思います。
今回調べたのは念のためと言うことで。