Java8新特性
java8 就是JDK8,这个版本,目前是国内市场主流的一个开发版本。它支持函数式编程,新的Javascript引擎,新的日期类,新的Stream API。
- lambda表达式:允许把函数作为一个方法的参数(把函数传递进方法)
- 方法引用:可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使代码看起来更加的简洁,减少冗余代码。
- 默认方法:default关键字修饰方法,在接口里边定义一个方法,包含方法体,所有实现或者继承这个接口的类或接口,都拥有了这个方法,并且可以直接调用。
- Stream API。可以理解为一个集合或者数组的流水线操作。
- Date Time API新的日期时间类。比之前咱们学的安全,好用。
- OPtional类 解决空指针异常
- Nashorn和javascript引擎。
第一章:lambda表达式
1.1【掌握】lambda表达式的概念
lambda表达式可以看成是一个匿名内部类,允许把函数作为一个方法的参数,将代码想参数一样进行传递,使用lambda表达式,可以使得代码更加简洁。
<函数式接口> <变量名>=(参数1,参数2,….)->{
// 方法体
}
这里是一个减号和大于号,注意:与ES6(js的常用版本)里边的lambda表达式有区别,那里是”=>”。
1.2【掌握】认识lambda表达式之后,那么为什么要使用这个lambda表达式呢?
- 因为简单,简洁。可以实现多个策略的模式,很多可以实现简单操作处理。
案例需求:假如现在有个大王,要从100个人中选出几个美女作为压寨夫人的候选人。要根据大王条件来选。
案例:
package com.qianfeng.java8.monday.lambda.demo; import java.util.ArrayList; import java.util.List; /** * 作者:黎杭 * 日期:2020/2/17 *
|
---|
User类
package com.qianfeng.java8.monday.lambda.demo; import java.io.Serializable; /** * 作者:黎杭 * 日期:2020/2/17 *
|
---|
案例升级版:
package com.qianfeng.java8.monday.lambda.demo1; import com.qianfeng.java8.monday.lambda.demo.User; import java.util.ArrayList; import java.util.List; /** * 作者:黎杭 * 日期:2020/2/17 *
|
---|
插入条件接口子类:
public interface Condition boolean test(V v);// 检测符不符合条件 } |
---|
public class FindGirl implements Condition @Override public boolean test(User user) { return user.getAge() < 26 && 16 < user.getAge() && “女”.equals(user.getSex());// 这个就是大王的第一次提的要求 } } |
public class FindMan implements Condition @Override public boolean test(User user) { return user.getAge() < 30 && 14 < user.getAge() && “男”.equals(user.getSex());// 这个就是大王的第一次提的要求 } } |
使用lambda表达式之后代码实例:
public class Test1 { public static void main(String[] args) { // 第一步,先创建一百个人,不管男女,随机创建 List for (int x = 0; x < 100; x++) { String sex = Math._random() < 0.5 ? “女” : “男”;// 随机取小于0.5就是女,否则是男 User user = new User(“竞选人” + x, 60 + x, 10.0 + x, x, sex);// crtl+q提示参数 list.add(user); } System.err.println(list); // 大王要求1:把年龄 16岁到26岁之间的女娃娃给我找出来! // 由于学了lambda表达式,所以这个匿名内部类,就可以简写// 这个就是大王的第一次提的要求 // 直接创建一个匿名内部类 List<_User> users = findUs_ersByCondition(list, user -> user.getAge() < 26 && 16 < user.getAge() && “女”.equals(us_er.getSex()));// 选出符合大王口味的人 System.err.println(users); // 大王要求2:这次年龄扩大到14岁到30岁女生都行 List System.err.printl_n(users1); // 大王又说了,不行,这次我需要男的给我找回来,找回来给我搬砖 // 这个时候就会发现一个问题,客户的需求总是在变化,每变化一次,我们就要修改方法,或者新增代码 List System.err.println(users2); // 注意观察,只需要修改方法参数即可,并且在修改具体实现类的test(检测)方法即可 } public static List List for (User u : list) { if (condition.test(u)) {// 等待外界传来条件,只要符合条件,就加入到结果集里边 resList.add(u);// 把当前这个符合条件的女娃娃放到结果集里边 } } _ retu_rn resList;// 返回所有符合条件的人,给大王 } } |
---|
1.3【掌握】使用lambda表达式注意事项
首先:语法要注意:()->{},左边部分(括号内)就是参数,花括号{}内就是方法主体
- 形参列表的数据类型会自动推算。
- 如果一个参数都没有,那么只需要保留一个空括号即可“()”
- 如果参数只有一个,那么这个括号可以省略,只需要写参数名称即可。
- 如果执行语句只有一句,并且没有返回值,那么花括号可以省略。如果有返回值,必须同时省略return关键字
- lambda表达式虽然是一个匿名内部类,但是不会生成单独的一个文件
- lambda表示若访问了局部变量, 则局部变量必须是final的,若没有加final关键字,系统会自动添加.(等下演示)
1.4【掌握】函数式接口
如果一个接口有且只有一个抽象方法,则该接口就可以称之为函数式接口。
案例:判断一个接口是否是函数式接口
@FunctionalInterface // 如果不是函数式接口的时候,那么会报错的,所以大家以后如果要写一个函数式接口,那么请加上@FunctionalInterface注解 public interface Condition boolean test(V v);// 检测符不符合条件 default String test2() {// 这个不是抽象方法 return “”; } } |
---|
函数式的接口就可以使用lambda表达式,由于有且只有一个抽象方法,所以lambda表达式的方法体就会被看成是这个抽象方法唯一的实现。说的再直接点就是这个方法主体代码,就是唯一的那个抽象方法的实现。
java为了程序员开发方便,提供一些内置的函数式接口,供程序员使用。
函数式接口 | 参数类型 | 返回类型 | 描述 |
---|---|---|---|
public interface Consumer |
T | void | 对给定的参数执行此操作。将传递进来的参数作为消费处理。这种接口就把它当作一个参数传递就行了。 |
public interface Supplier |
无参 | T | T get();返回类型为T的实例 |
public interface Function |
T | R | R apply(T t);将入参进行应用操作,得到R类型的返回值 |
public interface Predicate |
T | boolean | boolean test(T t);检测类型t是否满足某些条件,满足则返回true,不满足返回false |
供给型接口:
public class TestSupplier2 { public static void main(String[] args) { // Suibian // (int) (Math.random() * 100) 实际上是一个实例,它只是简写了! // 以下是完整的写法 // Suibian // @Override // public Integer getNum() { // return (int) (Math.random() * 100); // } // }; List * System.err.println(number_s); } // Suibian public static List List<Integer> list = new ArrayList<>(); Integer _i = sup.getNum();// get方法就是调用了 (int) (Math.random() 100)代码 li*st.add(i); return list; } } |
---|
传统方式代码:
public class Test { public static void main(String[] args) { Function String string = getSt_ring(789, f); System.err.println(string); } // 传统方式都能看懂 public static String getString(Integer i, Function // Integer integer = 99;// 先定义一个 整数数字 String res = f.apply(i);// 调用apply 实际上是调用 覆写方法中的主体代码:return String.valueOf(integer); return res; } } |
---|
public class Test2 { public static void main(String[] args) { // 把传进来的参数 数字变成字符串返回 Function String string = getSt_ring(999, f); System.err.println(string); } // 传统方式都能看懂 public static String getString(Integer i, Function // Integer integer = 99;// 先定义一个 整数数字 String res = f.apply(i);// 调用apply 实际上是调用 覆写方法中的主体代码:return String.valueOf(integer); return res; } } |
断言型函数式接口:
public class Test { public static void main(String[] args) { Predicate boolean b = te_st1(p); System.err.println(b); } public static boolean test1(Predicate User u = new User(“张三”, 170, 45.0, 22, “女”); boolean test = p return test; } } |
---|
public class FindGirl implements Predicate @Override public boolean test(User user) { return 16 < user.getAge() && 30 > user.getAge() && “女”.equals(user.getSex());// 认为合格 } } |
匿名内部类来实现:
public class Test2 { public static void main(String[] args) { Predicate @Override public boolean test(User user) { return 16 < user.getAge() && 30 > user.getAge() && “女”.equals(user.getSex());// 认为合格 } };// 匿名内部类实现 boolean b = test1(p); System.err.println(b); } public static boolean test1(Predicate User u = new User(“张三”, 170, 45.0, 22, “女”); boolean test = p.test(u);// 检测的结果 return test; } } |
---|
lambda表达式来实现:
public class Test3 { public static void main(String[] args) { // 认为合格 Predicate boolean b = t_est1(p); System.err.println(b); } public static boolean test1(Predicate User u = new User(“张三”, 170, 45.0, 22, “女”); boolean test = p return test; } } |
---|
第二章:【掌握】方法引用
方法引用是lambda表达式的更简洁的写法。使用的时候有条件:如果lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。
方法引用的语法:
- 对象::实例方法
- 类名::静态方法
- 类名::实例方法
- 类名::new
对象::实例方法的代码示例
public class Test { public static void main(String[] args) { // 先来一个消费型的函数式接口 Consumer Consumer consumer.accept(“你好”); consumer1.accept(“你好2”); } } |
---|
类名::静态方法名 lambda表达式代码:
public class Test2 { public static void main(String[] args) { // 先来一个消费型的函数式接口 Comparator Comparator int compare = comparator.compare(88, 88);// 第1种方法测试 System.err.println(compare); int compare1 = comparator2.compare(88, 88);// 第2种方法测试 System.err.println(compare1); } } |
---|
实例名称::方法名称
public class Test3 { public static void main(String[] args) { User user = new User(“李四”, 180, 60.0, 25, “男”); Supplier String name = sup.get();// 等同于 user.getName()方法了 System.err.println(“输出名字为:” + name); } } |
---|
对象::new
public class Test4 { public static void main(String[] args) { Supplier Supplier } } |
---|
第三章:【掌握】Stream API
待补充。。。。