Java8新特性
Java8概述
Java8(又称JDK1.8)是Java语言开发的一个主要版本。Oracle公司于2014年3月18日发布Java8。
- 支持Lambda表达式
- 函数式接口
- 新的Stream API
- 新的日期API
- 其他特性
对于公司而言,会用稳定版本,而非最新版本,因此Java8现在还是大多数企业的选择。
Lambda表达式
Lambda表达式:可以理解为特殊的匿名内部类,但语法更简介。
Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。
基本语法(=号左侧就是接口的声明,和匿名内部类一样)
<函数式接口> <变量名> = (参数1,参数2...) -> { //方法体 }
Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分
- 左侧:(参数1,参数2...)表示参数列表
- 右侧:{}内部是方法体
注意事项(使用时的规则)
- 形参列表的数据类型会自动推断
- 如果形参列表为空,只需保留()
- 如果形参只有1个,()可以省略,只需要形参的名称即可
- 如果执行语句只有一句,且无返回值,{}可以省略,若又返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句
- Lambda不会生成一个单独的内部类文件,而匿名内部类会
函数式接口
如果一个接口只有一个抽象方法,则该接口称之为函数式接口,只有函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。
@FunctionalInterface注解检测接口是否符合函数式接口。
常见的函数式接口
这些是JDK直接提供给外面的函数式接口,我们可以直接使用。
函数式接口 | 参数类型 | 返回类型 | 说明 |
Consumer<T>消费型接口 | T | void | void accept(T t);对类型为T的对象应用操作 |
Supplier<T>供给型接口 | 无 | T | T get();返回类型为T的对象 |
Function<T,R>函数型接口 | T | R | R apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。 |
Predicate<T>断言型接口 | T | boolean | boolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型。 |
Runnable | |||
Comparator | |||
下面来演示函数式接口的使用:
package com.qf; import java.util.function.Consumer; //Consumer接口 public class FunctionalInterfaceDemo02 { public static void main(String[] args) { //匿名内部类 Consumer<Double> consumer = new Consumer<Double>() { @Override public void accept(Double t) { System.out.println("聚餐消费:" +t); } }; happy(consumer,1000); //Lambda表达式 Consumer<Double> consumer1 = t-> System.out.println("聚餐消费:" +t); happy(consumer1,1000); //Lambda表达式 happy(t-> System.out.println("聚餐消费:" +t),1000); happy(t-> System.out.println("唱歌消费:" +t),2000); happy(t-> System.out.println("足疗消费:" +t),3000); } //Consumer 消费型接口 public static void happy(Consumer<Double> consumer,double money) { consumer.accept(money); } } //运行结果: /*聚餐消费:1000.0 聚餐消费:1000.0 聚餐消费:1000.0 唱歌消费:2000.0 足疗消费:3000.0*/
package com.qf; import java.util.Arrays; import java.util.Random; import java.util.function.Supplier; //Supplier public class FunctionalInterfaceDemo03 { public static void main(String[] args) { //0-100随机数5个 int[] arr = getNums(()->new Random().nextInt(100),5); System.out.println(Arrays.toString(arr)); } public static int[] getNums(Supplier<Integer> supplier,int count) { int[] arr = new int[count]; for (int i = 0; i < count; i++) { arr[i] = supplier.get(); } return arr; } }
package com.qf; import java.util.function.Function; //Function函数型接口 public class FunctionalInterfaceDemo04 { public static void main(String[] args) { String res = handlerString(s->s.toUpperCase(),"hello"); System.out.println(res); String result = handlerString(s->s.trim()," hello "); System.out.println(result); } public static String handlerString(Function<String, String> function, String str) { return function.apply(str); } }
package com.qf; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; //Predicate断言型接口 public class FunctionalInterfaceDemo05 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("zhangsan"); list.add("zhangwuji"); list.add("lisi"); list.add("wangwu"); list.add("zhaoliu"); List<String> res = filterNames(s -> s.startsWith("zhang"), list); System.out.println(res.toString()); List<String> result = filterNames(s -> s.length()>5, list); System.out.println(result.toString()); } //Predicate断言型接口 public static List<String> filterNames(Predicate<String> predicate, List<String> list) { ArrayList<String> resultList = new ArrayList<>(); for (String string : list) { if (predicate.test(string)) { resultList.add(string); } } return resultList; } }
方法引用
Lambda可以看作是匿名内部类的一种简写形式,而方法引用则是Lambda表达式第一种简写形式。如果Lambda表达式方法体中只是调用一个特定都已经存在的方法,则可以使用方法引用。
常用形式
- 对象::实例方法
- 类::静态方法
- 类::实例方法
- 类::new
Stream API