1. 程式人生 > >java8新特性---函式引數化(::)

java8新特性---函式引數化(::)

將函式作為引數化,並進行傳遞

1、定義函式介面

@FunctionalInterface
public interface ConvertPredict<T,V> {
    /**
     * 轉換函式
     * @param t
     * @param v
     */
    void convert(T t,V v);
}

2、定義一系列函式

  函式的簽名必須要跟函式介面的簽名相同,返回值型別相同,引數個數相同

public class ConvertData {

    /**
     * 汽車合格證識別提取模板
     * 
     * @param tableCell
     * @param formResponse
     */
    public static void vechileConvertSh(TableCell tableCell, VechileBody vechileBody) {
        
          // 函式體,要實現的方法
    }

    public static void vechileConvertBj(TableCell tableCell, VechileBody vechileBody) {
        
          // 函式體,要實現的方法
    }

}

3、函式呼叫

  1、 ConvertPredict<TableCell, VechileBody> predicate 為函式型別的 引數

  2、<TableCell, VechileBody>表示函式入參的型別

  3、predicate.convert(tableCell, vechileBody);表示呼叫相應的函式

  4、ConvertData::vechileConvertSh表示將該函式作為引數傳遞

    @Override
    public FormResponse formRecogtest(ChannelRequest channelRequest,
            String recogType) {

        // 省略。。。

        // 將原始資料處理成需要返回的資料
        if (recogType != null && recogType.equals(ChannelConst.VECH_SH)) {// 如果是xxxx汽車證
            return delResult(channelResponse, ConvertData::vechileConvertSh);
        } else {// 沒有指定合格證的型別
            return null;
        }

    }

    /**
     * 轉換識別結果
     * 
     * @param channelResponse
     * @return
     */
    private FormResponse delResult(ChannelResponse<TableData> channelResponse,
            ConvertPredict<TableCell, VechileBody> predicate) {

        // 省略。。。
        formResponse.setVechileBodys(vechileBodies);
        // 迴圈多張圖片資料
        for (OcrData<TableData> ocrData : channelResBody.getOcrDatas()) {
            // 一張圖片中可能有多張表格
            List<TableData> lisTableDatas = ocrData.getData();
            for (TableData tableData : lisTableDatas) {

                    // 省略。。。
                    for (TableCell tableCell : tableBody.getCellList()) {
                        // 將單元格對應到相應的返回資料中
                        predicate.convert(tableCell, vechileBody);
                    }
                }
                vechileBodies.add(vechileBody);
            }
        }
        return formResponse;

    }

以下為轉載

JDK8中有雙冒號的用法,就是把方法當做引數傳到stream內部,使stream的每個元素都傳入到該方法裡面執行一下。

以前的程式碼一般是如此的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public class AcceptMethod {

 

    public static void  printValur(String str){

        

System.out.println("print value : "+str);

    }

 

    public static void main(String[] args) {

        List<String> al = Arrays.asList("a","b","c","d");

        for (String a: al) {

            AcceptMethod.printValur(a);

        }

          //下面的for each迴圈和上面的迴圈是等價的 

        al.forEach(x->{

            AcceptMethod.printValur(x);

        });

    }

}

  現在JDK雙冒號是:

1

2

3

4

5

6

7

8

9

10

11

12

13

public class AcceptMethod {

    public static void  printValur(String str){

        System.out.println("print value : "+str);

    }

 

    public static void main(String[] args) {

        List<String> al = Arrays.asList("a""b""c""d");

        al.forEach(AcceptMethod::printValur);

        //下面的方法和上面等價的

        Consumer<String> methodParam = AcceptMethod::printValur; //方法引數

        al.forEach(x -> methodParam.accept(x));//方法執行accept

    }

}

   上面的所有方法執行玩的結果都是如下:

1

2

3

4

print value : a

print value : b

print value : c

print value : d

  在JDK8中,介面Iterable 中預設實現了forEach方法,呼叫了 JDK8中增加的介面Consumer內的accept方法,執行傳入的方法引數。

JDK原始碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

/**

     * Performs the given action for each element of the {@code Iterable}

     * until all elements have been processed or the action throws an

     * exception.  Unless otherwise specified by the implementing class,

     * actions are performed in the order of iteration (if an iteration order

     * is specified).  Exceptions thrown by the action are relayed to the

     * caller.

     *

     * @implSpec

     * <p>The default implementation behaves as if:

     * <pre>{@code

     *     for (T t : this)

     *         action.accept(t);

     * }</pre>

     *

     * @param action The action to be performed for each element

     * @throws NullPointerException if the specified action is null

     * @since 1.8

     */

    default void forEach(Consumer<? super T> action) {

        Objects.requireNonNull(action);

        for (T t : this) {

            action.accept(t);

        }

    }

 另外補充一下,JDK8改動的,在接口裡面可以有預設實現,就是在介面前加上default,實現這個介面的函式對於預設實現的方法可以不用再實現了。類似的還有static方法。現在這種介面除了上面提到的,還有BiConsumer,BiFunction,BinaryOperation等,在java.util.function包下的介面,大多數都有,字尾為Supplier的介面沒有和別的少數介面。