1. 程式人生 > >JAVA 8 函數式接口--Consumer

JAVA 8 函數式接口--Consumer

沒有 caller func 擴展 cal bject ble span rgs

從JDK8開始java支持函數式編程,JDK也提供了幾個常用的函數式接口,這篇主要介紹Consumer接口。
文本介紹的順序依次為:

  • 源碼介紹
  • 使用實例
  • jdk內對Consumer的典型使用
  • 擴展類介紹

源碼介紹

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
26
27
28
package java.util.function;

import java.util.Objects;

/**
*
* 表示“接受一個參數輸入且沒有任何返回值的操作“。不同於其它的函數式接口,Consumer期望通過方法的實現來執行具體的操作。
*/
@FunctionalInterface
public interface Consumer<T> {

/**
* 可實現方法,接受一個參數且沒有返回值
*/
void accept(T t);

/**
*
* 默認方法,提供鏈式調用方式執行。執行流程:先執行本身的accept在執行傳入參數after.accept方法。
* 該方法會拋出NullPointerException異常。
* 如果在執行調用鏈時出現異常,會將異常傳遞給調用鏈功能的調用者,且發生異常後的after將不會在調用。
*
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}

源碼只有2個方法,也比較容易理解,我們下面來看一下具體的使用方法。

使用實例

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
26
27
28
29
30
31
32
33
package jdk8;

import java.util.function.Consumer;

public class ConsumerTest {

public static void main(String[] args) {
testConsumer();
testAndThen();
}

/**
* 一個簡單的平方計算
*/
public static void testConsumer(){
Consumer<Integer> square = x -> System.out.println("print square : " + x * x);
square.accept(2);
}

/**
* 定義3個Consumer並按順序進行調用andThen方法,其中consumer2拋出NullPointerException。
*/
public static void testAndThen(){
Consumer<Integer> consumer1 = x -> System.out.println("first x : " + x);
Consumer<Integer> consumer2 = x -> {
System.out.println("second x : " + x);
throw new NullPointerException("throw exception test");
};
Consumer<Integer> consumer3 = x -> System.out.println("third x : " + x);

consumer1.andThen(consumer2).andThen(consumer3).accept(1);
}
}

下面是執行結果:

1
2
3
4
5
6
7
8
9
10
11
12
print square : 4

first x : 1
second x : 1
Exception in thread "main" java.lang.NullPointerException: throw exception test
at jdk8.ConsumerTest.lambda$testAndThen$2(ConsumerTest.java:27)
at java.util.function.Consumer.lambda$andThen$0(Consumer.java:65)
at java.util.function.Consumer.lambda$andThen$0(Consumer.java:65)
at jdk8.ConsumerTest.testAndThen(ConsumerTest.java:31)
at jdk8.ConsumerTest.main(ConsumerTest.java:9)

Process finished with exit code 1

在testAndThen()方法的執行結果可以看到打印的順序和出現異常的情況(third x : 1 並沒有輸出)
上面只是一個簡單的使用,主要為了說明使用方式。對於Consumer的工作實踐目前還未使用,並沒有好的例子。

jdk內對Consumer的典型使用

在jdk內對Consumer的典型使用非foreach莫屬了(在 java.lang.Iterable內),下面是源碼:

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);
}
}

方法接收一個Consumer對象,對this集合執行循環相同的操作。

TODO:除Iterable外還有很多地方使用到了Consumer,待後續使用到在添加。

擴展類介紹

Consumer的accept只接受一個參數,那如果要是想使用多個參數要怎麽辦?jdk8又提供了一個BiConsumer接口類,該類與Consumer的區別是可以接受2個參數。

jdk8還對Consumer和BiConsumer各提供了3個常用的相關接口類,見下表:

類名 描述
IntConsumer 接受單個int型參數的Consumer操作
DoubleConsumer 接受單個double型參數的Consumer操作
LongConsumer 接受單個long型參數的Consumer操作
ObjIntConsumer 接受2個int型參數的Consumer操作,不支持andThen方法
ObjDoubleConsumer 接受2個double型參數的Consumer操作,不支持andThen方法
ObjLongConsumer 接受2個long型參數的Consumer操作,不支持andThen方法

轉載鏈接:http://www.sanjinbest.com/uncategorized/JAVA-8-函數式接口-Consumer/

JAVA 8 函數式接口--Consumer