(原)
在上一篇,用到过这样一个方法:
list.forEach(new Consumer() { @Override public void accept(Integer t) { System.out.println(t); } });
这里重点看List的foreach方法;
/* * 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 * * For-each Loop * * * @paramthe type of elements returned by the iterator * * @since 1.5 * @jls 14.14.2 The enhanced for statement */public interface Iterable { /** * Returns an iterator over elements of type {@code T}. * * @return an Iterator. */ Iterator 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 * The default implementation behaves as if: *
{@code * for (T t : this) * action.accept(t); * }* * @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 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 * early-binding * spliterator from the iterable's {@code Iterator}. The spliterator * inherits the fail-fast 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 Spliteratorspliterator() { 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接口期望通过负作用去操作。(也就是说,它可能会操作传入的参数据,这里就是它所说的负作用。) * *This is a functional interface * whose functional method is {@link #accept(Object)}. *这是一个函数式接口,方法是accept * @param
the type of the input to the operation * * @since 1.8 */@FunctionalInterfacepublic interface Consumer
对于之前的例子,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("肉");
由于java8 ,runbable也改成了一个函数式接口,所以线在的线程可以这么写了:
new Thread(() -> System.out.print("123")).start();
例子请看这里: