Java Lambda

先来看一个简单的Lambda用法:java

//多行注释中为不使用Lambda的写法
        /**
        Runnable run = new Runnable() {
            @Override
            public void run() {
                System.out.println("Test")
            }
        };
         */
	   Runnable run = () -> System.out.println("Test");

咱们来看一下Runnable接口:数组

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

####咱们来看一下Java函数式接口【能够用Lambda方式的接口】的定义: 在Java中,函数式接口是只定义了一个抽象方法的接口。Java 8引入了FunctionalInterface注解来代表一个接口打算成为一个函数式接口。在实际使用中无论FunctionalInterface注解是否存在,Java编译器都会将全部知足该定义的接口看做是函数式接口。 下面咱们本身写一个接口看一下可否如Runnable通常:app

/**
 * 拿客
 * www.coderknock.com
 * QQ群:213732117
 * 建立时间:2016年07月22日
 * 描述:
 */
public interface TestLambdaInterface {
    void testInterface();
}

咱们以下使用该接口,程序能正常编译并输出结果,说明Java编译器都会将全部知足该定义的接口看做是函数式接口ide

TestLambdaInterface test=()->System.out.println("Test");
test.testInterface();

#####接口中定义方法的返回值无关性证实: 当咱们将方法的返回值改为String时:函数

TestLambdaInterface test=()->"test";
        test.testInterface();

说明函数式接口与接口中定义方法的返回值无关 下面咱们在接口中增长一个方法:ui

/**
 * 拿客
 * www.coderknock.com
 * QQ群:213732117
 * 建立时间:2016年07月22日
 * 描述:
 */
public interface TestLambdaInterface {
    void testInterface();
	void testInterface2();
}

编译时:code

D:\Work\LearnJavaFX\src>javac -encoding utf-8 LambdaTest.java
LambdaTest.java:20: 错误: 不兼容的类型: TestLambdaInterface 不是函数接口
        TestLambdaInterface test = () -> System.out.println("Test");
                                   ^
    在 接口 TestLambdaInterface 中找到多个非覆盖抽象方法
1 个错误

#####default与static方法的无关性证实: 咱们再来看看Java中提供的BinaryOperator接口:对象

package java.util.function;

import java.util.Objects;
import java.util.Comparator;

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {

    public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
    }

    public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}

其实现的接口BiFunction:接口

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface BiFunction<T, U, R> {

    R apply(T t, U u);

    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

该接口可使用以下方法生成实例:图片

BinaryOperator<Long> add = (x, y) -> x + y;

说明函数式接口与接口中是否存在default与static方法无关 ####总结 充分说明能成为函数式接口【可使用Lambda来简化接口操做】的条件为:只定义了一个抽象方法的接口。

Lambda的几种写法

import java.awt.event.ActionListener;
import java.util.function.BinaryOperator;

/**
 * 拿客
 * www.coderknock.com
 * QQ群:213732117
 * 建立时间:2016年07月22日
 * 描述:
 */
        /**
         * 对于只有一个抽象方法且返回值为void可使用下面的方法快捷的生成接口的实例
         */
        Runnable voidFunc = () -> System.out.println("没有参数的函数式接口");
        /**
         * 上面的声明其实完整写法应该为:
         *  Runnable voidFunc = () -> {System.out.println("没有参数的函数式接口")};
         * 对于只有一行语句时,能够省略{},
         * 下面是多行语句的状况,{}不能省略
         */
        Runnable muitiStatement = () -> {
            System.out.println("第一行");
            System.out.println("第二行");
            //多行语句....
        };

        /**
         * 对于有接口中有参数哦的方法咱们可使用
         * ActionListener oneParam = (event) -> System.out.println("一个参数");
         * 当只有一个参数时,能够省略()以下:
         */
        ActionListener oneParam = event -> System.out.println("一个参数");

        /**
         * 多参数就必须将参数放入到()中调用,按照参数顺序写入
         */
        BinaryOperator<Long> add = (x, y) -> x + y;

        /**
         * 上面几种状况中,接口的参数在编译时进行类型的推断,咱们亦能够显式声明一下【这样能够避免不少错误】
         */
        BinaryOperator<Long> add2 = (Long x, Long y) -> x + y;

在Lambda中引用变量需注意的事项

在JDK8对匿名内部类中调用类以外变量必须为final的限制进行了必定的放宽:

String name = "123";
        Runnable run = new Runnable() {
            @Override
            public void run() {
              	//在JDK8以前下面的语句是会报错的,只有name是final时才可使用,可是JDK8中,这样的语句就不会报错
                System.out.println(name);
            }
        };

虽然JDK8中上面的语句时能够的,但这只是减小了咱们代码中的编写,编译时仍是会将name当作是final因此当有如下几种状况时,编译仍是会报错:

//1.对name进行了第二次赋值,这样编译器就会认为name不是final类型
		String name = "123";
        name="";
        Runnable run = () -> {
            System.out.println(name);
        };
		//2.在匿名类方法中对变量进行赋值也是不容许的
		String name = "123";  
        Runnable run = () -> {
            name="";
            System.out.println(name);
        };

若是真的须要在Lambda中或者匿名中对变量赋值,那么应该将其放入数组,或者当作一个类的属性来传递【对象final时能够设置其属性,不能设置其引用】。 ####IDEA中快速生成Lambda语句 输入图片说明

相关文章
相关标签/搜索