Javaの勉強(6):ラムダ式
匿名クラス
普通Javaでクラスを定義して使う場合は,1つのファイルに1つのクラスを定義して使う.しかし再利用せず使い捨てをするクラスを使いたい場合,いちいち別ファイルに定義をしてからインスタンス生成をして,というようにするのは不便である.そこで,クラスの定義とインスタンス化を同時にできるようにしましょう,というのが匿名クラス(または匿名内部クラス)である.
匿名クラスの特徴として
がある.最後の特徴は,匿名クラスのインスタンスを参照するための参照変数を宣言するためには,既存クラス・インターフェース型の変数を用意しなければいけないためである.
以下に匿名クラスのコード例を示す.
// MyInterface.java public interface MyInterface { void myMethod(); }
public class LambdaMain { public static void main(String[] args) { System.out.println("This is example code for anonymous class."); MyInterface myInterface = new MyInterface() { @Override public void myMethod() { System.out.println("This is myMethod!"); } }; myInterface.myMethod(); } }
MyInterfaceの実装をmainメソッド内に直接書いている.myInterfaceからオーバーライドしたmyMethodを呼び出すと,実装した通りの動作をしていることがわかる.
匿名クラスの定義部分は他のメソッドの引数になっていることが多い.例えばComparatorインターフェースのcompareメソッドのオーバーライドをListイターフェースのsortメソッド内部に書くといったことがある.以下に例を示す.
//Student.java public class Student { private int studentNumber; private String name; public Student(String name, int studentNumber) { this.name = name; this.studentNumber = studentNumber; } public int getStudentNumber() { return this.studentNumber; } public String getStudentName() { return this.name; } @Override public String toString() { return studentNumber + " " + name; } }
//LambdaMain.java import java.util.ArrayList; import java.util.Comparator; import java.util.List; public class LambdaMain { public static void main(String[] args) { List<Student> list = new ArrayList<>(); list.add(new Student("akai", 1)); list.add(new Student("takahashi", 23)); list.add(new Student("yamamoto", 31)); list.add(new Student("nakasato", 17)); list.add(new Student("kishibe", 9)); for(Student s : list) { System.out.println(s); } list.sort(new Comparator<Student>(){ @Override public int compare(Student s1, Student s2) { return s1.getStudentNumber() - s2.getStudentNumber(); } }); System.out.println(); for(Student s : list) { System.out.println(s); } } }
list.sort引数にComparatorの実装を匿名クラスとして渡している.
ラムダ式
匿名クラスの定義をさらに簡略化したものがラムダ式である.ラムダ式は,どのクラス・インターフェースの定義かが推定でき,かつ匿名クラスで実装していたメソッドが1つでどのメソッドの定義なのかが推定できる場合に使える.
ラムダ式は初見では非常にとっつきにくく感じてしまうが,結局やっていることは「抽象メソッドのオーバーライド」である.オーバーライドするときに行くつかの条件が揃ったときにラムダ式が使えるようになる.
ラムダ式は(引数) -> {処理}
の形で書く.例えばComparatorインターフェースはcompareメソッドのみを定義すれば良いため,上記コードはラムダ式を使って次のように書くことができる.
list.sort((s1,s2) -> s1.getStudentNumber() - s2.getStudentNumber());
ラムダ式は