Lanbda表达式 java8新特性
1. 函数式接口
2. Lambda表达式使用
3. Lambda表达式中方法引用与构造器引用
4. Lambda表达式中this与super关键字
5. Lambda表达式的目标类型及变量作用域问题
6. 常用函数式接口
1. 函数式接口
要想了解Lambda表达式是什么, 就必须弄明白什么是函数式接口.
对于只有一个抽象方法的接口,需要这种接口的对象时, 就可以提供一个lambda表达式. 这种接口称为函数式接口.
这段定义摘自 <java核心卷|> . 不过需要注意的是: 函数式接口可以包含多个默认方法, 类方法, 但只能声明一个抽象方法.
如果自己想定义一个函数式接口, 可以在接口上加上 @FunctionalInterface 注解 , 不过该注解对程序功能没有任何作用,它用于告诉编译器执行更严格检查(检查是否只有一个抽象方法,否则会报错).
以下是jdk1.8中的函数式接口举例:
@FunctionalInterface
public interface IntToLongFunction {/*** Applies this function to the given argument.** @param value the function argument* @return the function result*/long applyAsLong(int value);
}
2. Lambda表达式使用
lambda表达式主要由三部分组成:
1. 形参列表: 形参列表允许省略形参类型. 如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略.
2. 箭头(->): 必须通过英文中画线号和大于符号组成.
3. 代码块: 如果代码只包含一条语句, Lambda表达式可以省略代码花括号. Lambda只有一条return语句,甚至可以省略return关键字.
示例:
/*** 函数式接口 : 方法无返回值, 无参数* @FunctionalInterface 声明是函数式接口*/
@FunctionalInterface
public interface Eatable {void taste();}public class LambdaTest {public static void main(String[] args) {/*** Eatable接口中taste()方法 无返回值, 无参数* 代码块中只有一条语句 可省略"{}" 无参数 不可省略"()"* 完整代码: () -> {System.out.println("苹果味道不错!");};*/Eatable eatable = () -> System.out.println("苹果味道不错!");eatable.taste();}}
/*** 函数式接口 方法有参数 无返回值*/
public interface Flyable {void fly(String weather);}public class LambdaTest {public static void main(String[] args) {/*** Flyable接口中fly()方法 无返回值, 有参数* 有一个参数可以省略"()" 及参数类型* 代码块只有一行代码 可省略"{}"* 完整代码: (String weather) -> { System.out.println("今天天气如何? " + weather);};*/Flyable flyable = weather -> System.out.println("今天天气如何? " + weather);flyable.fly("天气很好!");}}
/*** 函数式接口 有两个参数 有返回值*/
public interface Addable {int add(int a,int b);}public class LambdaTest {public static void main(String[] args) {/*** Addable接口中add()方法 有两个参数 有返回值* 方法中有两个参数, 所以不可省略"()" 但可省略参数类型* 代码块中只有一条返回语句 所以可省略"{}" 和 "return" 语句* 完整代码: (int a, int b) -> {return a+b ;};*/Addable addable = (a,b) ->a + b;int add = addable.add(1, 2);System.out.println(add); // 3}}
其实看到这里,我们已经大致掌握了lambda表达式的语法规则了.
那么究竟什么是lambda表达式呢?
lambda表达式是一个可传递的代码块,可以在以后执行一次或多次. (java核心卷|)
当然lambda也可以看成是匿名内部类的一种简写形式. 当使用lambda表达式替代匿名内部类创建对象时, Lambda表达式的代码块会替代实现抽象方法的方法体, Lambda表达式就相当于一个匿名方法.
某个方法在使用Lambda表达式时, 会接收 实现了该函数式接口的某个类的对象. 这些对象和类的管理完全取决于具体实现, 与
使用传统的内部类相比, 这样可能会高效得多.
3. Lambda表达式中方法引用与构造器引用
前面我们说到, 如果lambda表达式的代码块只有一条代码, 程序就可以省略lambda表达式中代码块的"{}".
不仅如此, 如果lambda表达式的代码块只有一条代码, 还可以在代码块中使用方法引用和构造器引用继续简化代码.
/*** Lambda 中方法引用和构造器引用** 主要有三种语法格式:* 对象::实例方法名* Employee employee = new Employee("张三",13,9000.00);* Supplier<String> supplier = () -> employee.getName();* Supplier<String> supplier2 = employee::getName;** 类::静态方法名* Comparator<Integer> com = (x,y) -> Integer.compare(x,y);* Comparator<Integer> com2 = Integer::compareTo;** 类::实例方法名* BiPredicate<String, String> bp = (x,y) -> x.equals(y);* BiPredicate<String,String> bp2 = String::equals;** 要求: 函数式接口的参数和返回值类型 要和 调用方法的参数返回值类型一致* 比如: Consumer<String> void accept(String str) 和 System.out void println(String x)** 构造器引用:* ClassName::new 具体调用哪个构造器取决于调用方法有几个参数* 比如:* Supplier<Employee> su = () -> Employee::new // 调用的无参数构造器 因为Supplier 中 get()方法无参数** Function<Integer,Employee> fun = (x) -> Employee::new // 调用了一个参数构造器, Function中 apply(T t)有参数* 数组引用:* Function<Integer,String[]> fun = x -> new String[x];* Function<Integer,String[]> fun2 = String[]::new*/
方法引用:
1. 引用类方法:
@FunctionalInterface
public interface Converter {// 该方法的目的为 将传入的 字符串 转为 数字类型 具体实现使用 Integer类的 parseInt()方法Integer convert(String from);
}public class LambdaTest {public static void main(String[] args) {// 普通lambda写法Converter converter = from -> Integer.parseInt(from);Integer convert = converter.convert("123");System.out.println(convert.getClass());// 引用类方法 // 注意: 此种写法 from参数会自动传入Integer.parseInt()方法中Converter converter1 = Integer::parseInt;Integer convert1 = converter1.convert("321");System.out.println(convert1.getClass());}}
2. 引用特定对象的实例方法:
@FunctionalInterface
public interface Converter {Integer convert(String from);
}public class LambdaTest {public static void main(String[] args) {// 普通lambda写法 具体实现为查询指定字符串的位置Converter converter2 = from -> "fkit.org".indexOf(from);Integer it = converter2.convert("it");System.out.println(it);// 引用特定对象的实例方法 "fkit.org" 字符串为String 类的一个实例// 参数from 会自动传入 indexOf()方法中Converter converter3 = "fkit.org"::indexOf;Integer it1 = converter3.convert("it");System.out.println(it1);}}
3. 引用某类对象的实例方法:
public interface MyTest {// 该方法为 根据 String int int 三个参数生成一个String 的返回值 a.substring(b,c)String test(String a,int b,int c);}public class LambdaTest {public static void main(String[] args) {// 普通lambda写法MyTest mt = (a,b,c) -> a.substring(b,c);String str = mt.test("Java I Love Yor", 2, 9);System.out.println(str);// 引用某类对象的实例方法// 注意这种写法的参数使用: 第一个参数会作为方法调用者,后面的参数会传入方法中MyTest mt1 = String::substring;String str1 = mt1.test("Java I Love You", 2, 9);System.out.println(str1);}}
由此可见: 我们使用方法引用,有时是因为已经有现成的方法可以完成想要传递到其他代码的某个动作(就是说我们在lambda代码块中写的功能有现成的类或方法可以使用).
构造器引用: 构造器引用与方法引用类似, 只不过方法名为new.
public interface YourTest {JFrame win(String title);}public class LambdaTest {public static void main(String[] args) {// 普通lambda写法 返回一个对象YourTest yt = title -> new JFrame(title);JFrame title = yt.win("title");System.out.println(title);// 引用构造器 函数式接口中被实现的全部方法参数传给该构造器作为参数// title 将会被传入 new JFrame(title) 中YourTest yt1 = JFrame::new;JFrame title1 = yt1.win("title");System.out.println(title1);}}
4. Lambda表达式中this与super关键字
可以在方法引用使用this与super关键字.
使用this关键字时, 要注意,是指创建这个lambda表达式的方法的this参数.
public class Application {public void init(){ActionListener listener = event -> {// 注意 this.toString() 会调用Application对象的toString方法, 而不是ActionListener实例的toStringSystem.out.println(this.toString());};}}
上面的代码中, this.toString方法会调用Application对象的toString方法,不是ActionListener实例的方法,
同理: super 关键字 则为调用父类的方法.
5. Lambda表达式的目标类型及变量作用域问题
在上面的代码中我们都用了一种接口类型来接收表达式: 接口 接口名 = (参数) -> { ... }
那么我们是否可以使用Object类型类接收? 答案是不可以. 以下会报错:
Object obj = () -> {for(int i = 0 ; i<10 ; i++){System.out.println(i);} }
Lambda的目标类型必须是明确的函数式接口.
Lambda只能为函数式接口创建对象.
但是可以使用函数式接口对Lambda表达式进行强制类型转换 ( 以下用强转为 Runnbale 接口示例 )
Object obj = (Runnable)() -> {for(int i = 0 ; i< 10 ; i++){System.out.println(i);}}
上面对Lambda表达式执行了强制类型转换,这样就可以确定表达式的目标类型为 Runnable 函数式接口.
Lambda表达式的作用域:
@FunctionalInterface
public interface Displayable {void display();default int add(int a , int b){return a + b;}}public class LambdaAndInner {private int age = 12;private static String name = "今天天气不错";public void test(){String book = "你好 , Java";Displayable dis = () ->{System.out.println("book局部变量为: " + book); // 你好 , JavaSystem.out.println("外部类的age实例变量为: " + age); // 12System.out.println("外部类的name类变量为: " + name); // 今天天气不错//System.out.println(add(3,5)); // Lambda中不允许调用接口中定义的默认方法};dis.display();System.out.println(dis.add(3,5));}public static void main(String[] args) {LambdaAndInner lambda = new LambdaAndInner();lambda.test();}}
注意: 与内部类类似, 在Lambda中, 只能引用值不会改变的变量.
Lambda表达式中获取的变量必须实际上是最终变量, 这个变量初始化后不会再为它赋新值.(相当于加了final,隐式final).
6. 常用函数式接口
/**** 常用函数式接口:* Runnable void run() ,* Comparator<T> int compare(T o1, T o2);** Java内置四种常见函数式接口* Consumer<T> 消费型接口 void accept(T t) ,* Supplier<T> 供给型接口 T get()* Function<T,R> 函数型接口 R apply(T t)* Predicate<T> 断言型接口 boolean test(T t)** 其他函数式接口* BiFunction<T,U,R> R apply(T t, U u)* * UnaryOperator<T>(Function 子接口) T apply(T t)** BinaryOperator<T>(BiFunction 子接口) T apply(T t1, T t2)** BigConsumer<T,U> void accept(T t,U u)** ToIntFunction<T> ToLongFunction<T> ToDoubleFunction<T> 参数为T 返回值分别为int long double** IntFunction<R> LongFunction<R> DoubleFunction<R> 参数分别为int long double 返回值为 R*/
Lanbda表达式 java8新特性相关推荐
- java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合
java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...
- java8新特性(1)--- lambda表达式
java8新特性(1)- lambda表达式 函数式编程,简化开发 新增语法(->) package com.common.jdk8;// 试想,如果在jdk1.7中,我们要实现基于这个接口的加 ...
- java8新特性lambda表达式、函数式编程、方法引用和接口默认方法以及内部类访问外部变量
一提到java是一种什么语言? 大多数人肯定异口同声的说是一门面向对象的语言,这种观点从我们开始学java就已经根深蒂固了,但是学到java8新特性函数式编程的时候,我才知道java并不是纯面向对象的 ...
- 【java8新特性】——lambda表达式与函数式接口详解(一)
一.简介 java8于2014年发布,相比于java7,java8新增了非常多的特性,如lambda表达式.函数式接口.方法引用.默认方法.新工具(编译工具).Stream API.Date Time ...
- Java8新特性总结 - 3. Lambda表达式
所有示例代码打包下载 : 点击打开链接 Java8新特性 : 接口新增默认方法和静态方法 Optional类 Lambda表达式 方法引用 Stream API - 函数式操作流元素集合 Date/ ...
- Java8新特性学习_001_(Lambda表达式,函数式接口,方法引用,Stream类,Optional类)
目录 ■代码 ■代码运行结果 ■代码说明 ・44行:Stream的.foreach方法ー参数类型:函数式接口 ・82行:Interface中,default方法 ・92行 Stream的.max方 ...
- Java8新特性(一)—————Lambda表达式
关注微信公众号[行走在代码行的寻路人]获取Java学习视频及资料. 简述Java8中的新特性: 1.速度快:两个对象比较,采用红黑树替换了链表,使其速度变快新增的速度比较与链表较慢 2.新增Lambd ...
- java8新特性之lambda表达式--超级详细版本
java8新特性之lambda表达式 1.什么是lambda表达式?为什么用它? 2. 为什么Java需要lambda表达式? 3. lambda表达式的语法 4.函数式接口 4.1 什么是函数式接口 ...
- java8新特性总结——lambda表达式
最近看尚硅谷java8新特性视屏,总结一下学习知识. Lambda表达式:是一个匿名函数,我们可以把Lambda理解为一段可以传递的代码(将代码像数据一样传递),可以写出更简洁更灵活的代码.作为一种更 ...
最新文章
- oracle em 乱码问题
- JQuery图表插件Highcharts示例教程
- MFC程序需要的函数库及头文件--《深入浅出MFC》
- SAP Spartacus user和org user form两处不同的checkbox风格
- 爬虫-xpath的用法强化
- 【转】JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解
- 限制内核printk的打印频率
- 禁用Chrome自动更新
- hdu 1394 Minimum Inversion Number
- 《尚硅谷大数据Hadoop》教程
- mysqldump逻辑备份
- R 语言怎么保存工作目录到当前路径_第一讲 R基本介绍及安装
- I-P-B frame简介
- Java程序员如何写简历,给大家一个小建议?
- cad批量打印快捷键_原来CAD还能这么打印?批量打印了解一下?1分钟打印100张...
- springboot项目层次结构_【SpringBoot】多模块项目结构搭建
- Cannot load library /home/yx/Qt5.3.0/Tools/QtCreator/lib/qtcreator/plugins/QtProject/libHelp.so:
- 确定目标:利用web分析技术诱捕受害者
- 2014微软秋季校招算法笔试题
- 【黑苹果】【高分屏】软件修改BIOS中DVMT等设置 Insyde BIOS 联想YOGA系列