JAVA SE 8 学习笔记 是在学习《写给大忙人看的java se 8》一书后进行复习总结,以备随时查看
如需学习详细内容,请支持正版图书
1. Lamda表达式
Lamda表达式是一段可以传递的代码,可以被执行多次。
语法:(参数..) -> {表达式}
例:
(String first, String second) -> {if(first.length() < second.length()) return -1; else return 0}
如果参数只有一个可以省略小括号
如果没有参数可以提供一堆空的小括号
如果参数类型可以被推导,那么可以省略参数类型
如果代码块只有一行可以省略大括号
对于只包含一个抽象方法的接口,称为函数式接口,可以通过Lamda表达式创建该接口的对象。
例:
Arrays.sort(words, (first, second) -> Integer.Compare(first.length(), second.length()));
可以在任意函数式接口上标注@FunctionalInterface,这样编译器会检查该实体是否只包含一个抽象方法,并且javadoc页面也会包含一条声明
该注解不要求强制使用,但是会让代码更清楚
方法引用
当想要传递给其他代码的操作,已经有了实现的方法,则可以使用方法引用。可以理解为,针对传递既有方法时的,lamda表达式的简写
语法:
对象::实例方法
类::静态方法
类::实例方法
前两种情况中,方法引用等同于提供方法参数的lamda表达式
例:
Math::pow等同于(x, y) -> Math.pow(x, y);
第三种情况,第一个参数会成为执行方法的对象
例:
String::compareToIgnoreCase等同于(x, y) -> x.compareToIgnoreCase(y);
还可以捕获方法引用中的this/super参数
例:
this::equal 等价于x->this.equals(x)
Thread t = new Thread(super::toString);
构造器引用
构造器引用同方法引用类似,不同的是在构造器引用方法中方法名是new
对于拥有多个构造器的类,会根据上下文选择最合适的构造器
例:
List<String> labels = ..;
Stream<Button> stream = labels.stream().map(Button::new);
List<Button> buttons = stream.collect(Collectors.toList());
此处会调用Button(String)构造器
数组构造器引用可以解决”无法创造一个泛型数组“的问题
Button[] buttons = stream.toArray(Button[]::new);
变量作用域
lambda表达式可以捕获闭合作用域中的变量的值,这些变量称为自由变量。例如可以将lambda表达式转换为一个只含一个方法的对象,此时自由变量的值被复制到该对象的实例中
例:
public static void repeatMessage(String text, int count) {
Runnable r = () -> {
for(int i=0; i< count; i++) {
System.out.println(text);
}
};
new Thread(r).start();
}
在lambda表达式中被引用的变量不可更改,但是变量引用的值可以更改。这不是线程安全的,不建议这么做。
lambda表达式中不允许声明与一个局部变量同名的参数或局部变量
lambda表达式中this代表创建该lambda表达式的方法的this
例:
public class Application {
public void doWork() {
Runnable r = () -> {...; this.toString();}
}
}
此时调用Application的toString()
默认方法
Java SE 8 允许接口包含带有具体实现的方法(称为默认方法)
默认方法遵从以下两个规则:
1. 类优先:当父类中存在与接口中默认方法同名同参数的方法时,父类中的方法会起作用
例:
假设Person, Name中都存在getName()默认方法。
class Student extends Person implements Named { ... }
此时只有父类方法起作用。类优先可以保证与Java7的兼容性
2. 当实现的两个接口中包含同名同参数的方法时, 编译器会报错,要求开发人员自行实现此方法。(可以在实现中选择调用其中一个接口的方法)
例:
假设Person, Name中都存在getName()默认方法。
解决冲突:
class Student implements Person, Named {
public String getName() { return Person.super.getName(); }
}
接口中的静态方法
Java 8中接口可以添加静态方法,这样就不比再为一个工具方法提供辅助类,并且可以灵活运用函数的强大。
例如List接口提供了一个排序方法,接收一个“键提取”函数
例:
首先,定义compareByNameThenAge方法定义比较的行为public static int compareByNameThenAge(Human lhs, Human rhs) {
if (lhs.name.equals(rhs.name)) {
return lhs.age - rhs.age;
} else {
return lhs.name.compareTo(rhs.name);
}
}
接着使用这个引用去调用humans.sort方法:
humans.sort( Human::compareByNameThenAge);