Java Lambda
2016-07-22 00:00
651 查看
摘要: Java Lambda
先来看一个简单的Lambda用法:
我们来看一下Runnable接口:
####我们来看一下Java函数式接口【可以用Lambda方式的接口】的定义: 在Java中,函数式接口是只定义了一个抽象方法的接口。Java 8引入了FunctionalInterface注解来表明一个接口打算成为一个函数式接口。在实际使用中不管FunctionalInterface注解是否存在,Java编译器都会将所有满足该定义的接口看作是函数式接口。
下面我们自己写一个接口看一下能否如Runnable一般:
我们如下使用该接口,程序能正常编译并输出结果,说明Java编译器都会将所有满足该定义的接口看作是函数式接口:
#####接口中定义方法的返回值无关性证明:
当我们将方法的返回值改成String时:
说明函数式接口与接口中定义方法的返回值无关
下面我们在接口中增加一个方法:
编译时:
#####default与static方法的无关性证明:
我们再来看看Java中提供的BinaryOperator接口:
其实现的接口BiFunction:
该接口可以使用如下方法生成实例:
说明函数式接口与接口中是否存在default与static方法无关
####总结
充分说明能成为函数式接口【可以使用Lambda来简化接口操作】的条件为:只定义了一个抽象方法的接口。
虽然JDK8中上面的语句时可以的,但这只是减少了我们代码中的编写,编译时还是会将name当做是final所以当有以下几种情况时,编译还是会报错:
如果真的需要在Lambda中或者匿名中对变量赋值,那么应该将其放入数组,或者当做一个类的属性来传递【对象final时可以设置其属性,不能设置其引用】。
####IDEA中快速生成Lambda语句
先来看一个简单的Lambda用法:
//多行注释中为不使用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一般:
/** * 拿客 * www.coderknock.com * QQ群:213732117 * 创建时间:2016年07月22日 * 描述: */ public interface TestLambdaInterface { void testInterface(); }
我们如下使用该接口,程序能正常编译并输出结果,说明Java编译器都会将所有满足该定义的接口看作是函数式接口:
TestLambdaInterface test=()->System.out.println("Test"); test.testInterface();
#####接口中定义方法的返回值无关性证明:
当我们将方法的返回值改成String时:
TestLambdaInterface test=()->"test"; test.testInterface();
说明函数式接口与接口中定义方法的返回值无关
下面我们在接口中增加一个方法:
/** * 拿客 * www.coderknock.com * QQ群:213732117 * 创建时间:2016年07月22日 * 描述: */ public interface TestLambdaInterface { void testInterface(); void testInterface2(); }
编译时:
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语句
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树