Java8 Pratice - Lambda -2 functional interface

先來一個簡單可以執行的範例如下

Parse.java
package com.kirin.java8.lambada;

public interface Parse {
	
	public void showLineNumber(int count);

}

DocParser.java
package com.kirin.java8.lambada;

import java.util.ArrayList;
import java.util.List;

public class DocParser {
	
	private List<String> docLines = new ArrayList<String>();
	
	public void showLineNumber(Parse p){
		p.showLineNumber(docLines.size());
	}
}
TestMain.java
package com.kirin.java8.lambada;

public class TestMain {
	
	public static void main(String[] args){
		DocParser tc = new DocParser();
		tc.showLineNumber(i-> System.out.println("Number is"+ i));  //A
	}

}


在A列中可以用lamda 執行 此方法,那麼如果我們在 Parse 增加了另一個方法會發生什麼事情如下

Parse.java
package com.kirin.java8.lambada;

import java.util.List;

public interface Parse {
	
	public void showLineNumber(int count);
	
	public void showDocSize(List<String> doc);

}
此時的的TestMain.java 就會發生錯誤,好那我們就先做一假設是因為我們沒有明確指定型別,好我們改變如下
package com.kirin.java8.lambada;

public class TestMain {
	
	public static void main(String[] args){
		DocParser tc = new DocParser();
		tc.showLineNumber((int i)-> System.out.println("Number is"+ i));
	}

}
但是事與願違,標紅色的地方還是Compile 錯誤,好那我們來看一下Java 跟我們說是發生什麼錯誤 :
       The target type of this expression must be a functional interface
OK , 原來要用Lambda 表示式,不是全部的interface 都可以用,那什麼是 functional interface
,簡單來說就是 一個interface 裡面只能存在一個方法,像是 java Runnable
,但是這樣好像很不踏實,如果原本是要用來做 Lambda 表示式interface 被後來加入了一個方法不是就壞了,此時Java 提供了 @FunctionalInterface annotation 使用方法如下

Parse.java
package com.kirin.java8.lambada;

import java.util.List;

@FunctionalInterface
public interface Parse {
	
	public void showLineNumber(int count);
	
	public void showDocSize(List<String> doc);

}
此時Parse.java 就會出現 Compile Error
Invalid '@FunctionalInterface' annotation; Parse is not a functional interface
要把方法留到剩一個,這樣才不會錯誤,

延伸討論

A .如果 FunctionalInterface 遇到 interface extends 這麼辦,如下
Parse.java
package com.kirin.java8.lambada;

import java.util.List;

@FunctionalInterface
public interface Parse extends Runnable {
	
	public void showLineNumber(int count);
}
很不幸的是不行的

B. 如果Parse.java 讓別人繼承如下
package com.kirin.java8.lambada;

@FunctionalInterface
public interface Parse  {
	
	public void showLineNumber(int count);
}

interface Test extends Parse{
	
}
依annotation 定義只對當前的class 有效過,所以這是OK的

C. 如果遇到 Java8 的預設方法 如下
Parse.java
package com.kirin.java8.lambada;

@FunctionalInterface
public interface Parse  {

public void showLineNumber(int count);

default void test(int count){
for(int i=0;i<10 font="" i="">
showLineNumber(i);
}
}

}
這樣是OK的喔,因為 Lamnda 只要留一個未明確實做的方法傳入即可,那default 方法已經明確實作了,所以是可以的



-----------------------------------------------------------------------



Java 幫我們提供了幾種常用的 Functional interface 可以參考 java.util.function package 下的Class,





那麼下一節會探討 這些Java 提供的Functional interface 作用 和 stream 的互動關係




留言

這個網誌中的熱門文章

Google Map 單車路徑計算坡度和角度小工具

angular 如何Http 如何設定 CORS (Cross-Origin Resource Sharing)