首页 > 代码库 > Java8学习笔记(二)-函数式接口与方法引用

Java8学习笔记(二)-函数式接口与方法引用

一、Lambada表达式到底是什么

  首先先看一下下面的一段代码!

package cn.org.kingdom.jdk8;
@FunctionalInterface
interface MyInterface {
	void test();
	String toString();
}
public class Test {
	public void test(MyInterface inter) {
		System.out.println("*************************");
		inter.test();
		System.out.println("*************************");
	}
	public static void main(String[] args) {
		Test t = new Test();
		t.test(()->{
			System.out.println("lambada表达式实现");
		});
		MyInterface my =()->{};
		System.out.println(my);
		System.out.println(my.getClass());
		System.out.println(my.getClass().getSuperclass());
		System.out.println(my.getClass().getInterfaces()[0]);
	}
}
打印结果如下

*************************
lambada表达式实现
*************************
cn.org.kingdom.jdk8.Test$$Lambda$2/9195351@18025c
class cn.org.kingdom.jdk8.Test$$Lambda$2/9195351
class java.lang.Object
interface cn.org.kingdom.jdk8.MyInterface

二、下面再次看一下之前的例子
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
list.forEach(new Consumer<Integer>() {
	@Override
	public void accept(Integer t) {
		System.out.println(t);
	}
});		        

对于list的foreach方法我们来看一下,这个方法的定义在什么地方

public interface Iterable<T> {
    Iterator<T> iterator();
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

对于以上的代码,我们可以看出在jdk1..8中,接口中增加了默认方法(保证了jdk1.8新特性的加入,同时也保证了jdk8与老版本的兼容),下面我们重点研究一下这个foreach方法

/**
* 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.

翻译如下:对于这个接口的每个元素执行给定的参数,直到所有的元素都被处理完毕,或者说操作抛出了一个异常,如果没有被实现类所指定的话,动作会被按照迭代的顺序来执行

是否抛出异常取决于调用者

*/

接下来,在看下Consumer接口的定义

package java.util.function;
import java.util.Objects;

/**
* 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.
* 代表一个操作,这个操作接受一个单个的输入参数,并且不产生结果,和大多数函数接不同的是,它可能会产生副作用 * * <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> { /** * Performs this operation on the given argument. * @param t the input argument */ void accept(T t); /** * Returns a composed {@code Consumer} that performs, in sequence, this * operation followed by the {@code after} operation. If performing either * operation throws an exception, it is relayed to the caller of the * composed operation. If performing this operation throws an exception, * the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }

接下来,使用函数式接口的方式来对案例进行重新实现

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
list.forEach(i->{
	System.out.println(i);
});

Lambda表达式为java添加了缺失的函数式编程特性,使我们能将函数当成一等公民看待
在将函数作为一等公民的语言中,Lambda表达式的类型是函数,但在java中,Lambda表达式是对象,他们必须依附一类特别的对象类型-函数式接口

也可以通过以下方式进行实现

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
//通过方法引用(method references)
list.forEach(System.out::print);

好了,今天就写到这里!关于Lambda表达式的基本使用,相信大家应该有一个基本的认识了

Java8学习笔记(二)-函数式接口与方法引用