java8新特性,包括方法引用、Optional
一、方法引用 1.理解lambda表达式是对函数式接口的一种匿名实现,也就是入参、出参都符合的情况下,加了函数体。
如果函数体只是调用了已有的方法,此时入参、出参、函数体3者都确定了,只需要把要调用的方法描述清楚即可,提供调用者(4种)、方法名即可,此时就可以用方法引用了,是lambda表达式的进一步简化。
于是,根据方法调用者的4种情况,有4种写法。
-
静态方法引用 : ClassName :: staticMethodName
没啥好说的,提供类名+方法名,参数自动补上 -
构造器引用 : ClassName :: new
没啥好说的,提供类名+方法名,参数自动补上 -
类的任意对象的实例方法引用: ClassName :: instanceMethodName
- 类的任意对象指的是由入参中传入的对象(第一个,后面的无论几个都是参数)来调用,也就是说,入参要比调用的方法的参数多一个。这种情况下,调用者是不确定的,调用的时候才确定
Arrays.sort(strs,(s1,s2)->s1.compareToIgnoreCase(s2)); //sort的参数比compareToIgnoreCase要多一个,多出来的就是调用者 Arrays.sort(strs, String::compareToIgnoreCase);
- 看到ClassName :: instanceMethodName,就表示,args0是调用者,后面的args是instanceMethodName的参数,相当于(args0,args...) -> args0.instanceMethodName(args...),args0是ClassName 类型的
- 入参的数量由接口决定,跟数据无法,比如前一个里面元素是map,那后面的方法引用也只能有一个入参。也就是说,一个运算符里面的函数类型是规定好的,方法引用写啥方法是有限制的,方法引用只是lambda的简化,功能远没有lambda强大。
比如下图,第二行就报错,因为方法引用无法传入自定义的入参;只能像第三行那样,调用一个无参的方法,除非接口支持,比如Arrays.sort,就支持2个参数
- 类的任意对象指的是由入参中传入的对象(第一个,后面的无论几个都是参数)来调用,也就是说,入参要比调用的方法的参数多一个。这种情况下,调用者是不确定的,调用的时候才确定
-
特定对象的实例方法引用 : object :: instanceMethodName
特定对象指的是在lambda外面创建的对象public class Test { public static void main(String[] args) { Test test = new Test(); // lambda表达式使用: Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(s -> test.println(s)); // 特定对象的实例方法引用: Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(test::println); } public void println(String s) { System.out.println(s); } }
- 无法显式传参
类的任意对象指的是由入参中传入的对象(第一个,后面的无论几个都是参数)来调用,也就是说,入参要比调用的方法的参数多一个。这种情况下,调用者是不确定的,调用的时候才确定
public class Student{
private String name;
private Integer score;
public void setNameAndScore(String name, Integer score)
{
this.name = name;
this.score = score;
System.out.println("Student "+ name +"'s score is " + score);
}
public static void main(String[] args)
{
//用变量接收lambda表达式,相当于给匿名函数起了个名
TestInterface testInterface = Student::setNameAndScore;
testInterface.set(new Student(), "DoubleBin", 100);
}
@FunctionalInterface
interface TestInterface
{
// 注意:入参比Student类的setNameAndScore方法多1个Student对象,除第一个外其它入参类型一致
public void set(Student d, String name, Integer score);
}
}
3.2 特定对象
test对象是lambda外创建的
public class Test
{
public static void main(String[] args)
{
Test test = new Test();
// lambda表达式使用:
Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(s -> test.println(s));
// 特定对象的实例方法引用:
Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(test::println);
}
public void println(String s)
{
System.out.println(s);
}
}
stream API
https://blog.csdn.net/mu_wind/article/details/109516995?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.nonecase
二、Optionalnull这个概念,本身就有争议,它使得方法的返回值变得更复杂。需要做非空判断,而Optional就是把非空判断这个逻辑给封装了。
当遇到一个变量可能null时,就可以用Optional把它封装起来,然后就可以调用Optional的api来进行操作,比如非空判断,比如为空时如何,不为空时如何。
Optional.ofNullable(student).map(u -> u.getGender()).orElseGet(() -> "Unkown");



