首页 > 代码库 > Java 8 新特性:2-消费者(Consumer)接口

Java 8 新特性:2-消费者(Consumer)接口

(原)

在上一篇,用到过这样一个方法:

list.forEach(new Consumer<Integer>() {

            @Override
            public void accept(Integer t) {
                System.out.println(t);
            }
            
        });

这里重点看Listforeach方法;

 

/*
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

/**
 * Implementing this interface allows an object to be the target of
 * the "for-each loop" statement. See
 * <strong>
 * <a href="http://www.mamicode.com/technotes/guides/language/foreach.html">For-each Loop</a>
 * </strong>
 *
 * @param <T> the type of elements returned by the iterator
 *
 * @since 1.5
 * @jls 14.14.2 The enhanced for statement
 */
public interface Iterable<T> {
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();

    /**
     * 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.
     *针对于Iterable的每一个元素去执行给定的动作,直到所有的元素都执行完,或者抛出异常。如果没有被这个实现类所指定,动作就会按照迭代的顺序来执行。是否抛出异常取决于调用者。
 *
     * @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);
        }
    }

    /**
     * Creates a {@link Spliterator} over the elements described by this
     * {@code Iterable}.
     *
     * @implSpec
     * The default implementation creates an
     * <em><a href="http://www.mamicode.com/Spliterator.html#binding">early-binding</a></em>
     * spliterator from the iterable‘s {@code Iterator}.  The spliterator
     * inherits the <em>fail-fast</em> properties of the iterable‘s iterator.
     *
     * @implNote
     * The default implementation should usually be overridden.  The
     * spliterator returned by the default implementation has poor splitting
     * capabilities, is unsized, and does not report any spliterator
     * characteristics. Implementing classes can nearly always provide a
     * better implementation.
     *
     * @return a {@code Spliterator} over the elements described by this
     * {@code Iterable}.
     * @since 1.8
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

 

  

该方法属于Iterable接口,并且是1.8新加的方法,它有一个默认的实现方法,用关键字default修饰,也就是说,在JDK1.8里,接口方不再必需是抽象方法了,而是可以有实现体的,并且这个有实现体的方法需要用default关键字来修饰。

 

再来看下Consumer接口。

 

/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 *代表了一个操作,接收了一个参数,并且不返回结果,不同于大多数其它的函数式接口,Consumer接口期望通过负作用去操作。(也就是说,它可能会操作传入的参数据,这里就是它所说的负作用。)
 *
 * <p>This is a <a href="http://www.mamicode.com/package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *这是一个函数式接口,方法是accept
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T>

 

  

对于之前的例子,list.forEach(i -> System.out.println(i)); 这个i是什么参数呢?由于这里只有一个参数据,编译器可以自动的推断出这个i所属的类型,同样,你也可以显示的指定它的类型,就像这样list.forEach((Integer i) -> System.out.println(i));,这里是必需要加上括号的。

 

在其它语言中,lambda表达式类型是函数,但是java中,lambda表达式是对象,他们必需依附于一个函数式接口(functional interface)。

所以对于函数式接口的实现,你可以这么写:

例如有如下函数式接口:

package com.demo.jdk8;

public interface Animal {
	void eat(String food);
}

  

在上一篇lambda中,对函数式接口有这样一句话

技术分享

1在调用的地方用lambda可以这么写(lamdba expressions):

Animal a = food -> {System.out.println(food);};
a.eat(“鱼”);

这么写和写一个类实现Animal接口,然后再new 出来效是一样的。但是这种写法代码会更简洁。

2、用方法引用可以这么写(method references):

Animal a = System.out::println;
a.eat("肉");

  

 

Java 8 新特性:2-消费者(Consumer)接口