Cou氏の徒然日記

ほのぼの日記ブログです。

Java の学習 (ラムダ式)

Java

前回、無名クラス(匿名クラス)を使った実装をしてみました。

◆ IPrintOut.java (インタフェース)
public interface IPrintOut {
  void print(String str);
}
◆ 実装クラス
  IPrintOut ipo = new IPrintOut() {
     @Override  
     public void print(String str){
         System.out.println("Call IPrintOut.print(). :" + str);
     }
  };
  ipo.print("test!");

 

無名クラス(匿名クラス)とはどんなものかがわかった状態で、次は「関数型インタフェース」について。

 

◆ 関数型インタフェース

関数型インタフェースとは、

  • 抽象メソッドを1つだけもっているもの

を指すようです。

つまり、複数の抽象メソッドを持つインタフェースは、関数型インタフェースになりません。

 

IPrintOutインタフェースは、

  • void print (String str) 

という抽象メソッドを1つだけ持っているので、関数型インタフェースになります。

 

こう考えると、インタフェースにつき1つメソッドを定義するというのが一般的になっていくのかもしれませんね。

もともとインタフェースは多重でimplementsできますので、必要なものを必要なだけ継承すればよいので、「1インタフェース=1抽象メソッド」というのはそういう意図があったのかもしれませんね。

 

実際、Java SEに用意されている関数型インタフェースもいっぱいありますね。

Runnableインタフェースは、マルチスレッドを使う場合によくお世話になるインタフェースなので、馴染みがあります。

Runnableインタフェースには、run() という抽象メソッドを1つだけ持つので、関数型インタフェースになります。

 

ちなみに、関数型インタフェースかどうかをチェックするためには、

@FunctionalInterface アノテーション」をつけることで、関数型インタフェースかどうかを自動チェックできます。

実際に、2つ目の抽象メソッドを定義してみると…関数型インタフェースではないというエラーが出ます。

 

ラムダ式

ラムダ式とは、「無名クラス(匿名クラス)を利用して、関数型インタフェースを簡単に作るための記述方法」という感じでしょうか。

基本構文としては…

 ( 引数1, 引数2, …)  ->  { 処理 }

という感じで記述します。

上記のように、インタフェース名やメソッド名が全く登場しないので、かなり違和感がありますが、このような記述を許容するのは、関数型インタフェースであることが前提であるという制約があります。

ただ、関数型インタフェースであるからこそ、メソッド名を省略しても、引数の型などがすべて決まり、だからこそ省略できます…ということでしょうね。

 

実際、先程の文をラムダ式に書き換えてみると、

VSCodeなどのエディタなら、関数型インタフェースであれば、自動で書き換えてくれますので便利ですし、ラムダ式での記述が推奨されているんでしょうね。

 

  IPrintOut ipo = (str) -> {
      System.out.println("Call IPrintout.print(). :" + str);
  };
  ipo.print("test!"); 

すごく単純になりました。

確かに最低限の情報のみになりましたが、ラムダ式や無名クラス(匿名クラス)のことを知らないと、どこから print というメソッド名は出てきたのか?とかわからないですね。

だからこそ、当時自分は「???」となってJavaソースを読むのをあきらめたわけですが。