概述
Java8 (又称 JKD1.8) 是 Java 语言开发的一个主要版本。
Oracle公司于2014年3月18日发布Java8 。
- 支持Lambda表达式
- 函数式接口
- 新的Stream API
- 新的日期 API
- 其他特性
一、Lambda表达式
1.1概述
Lambda是一种特殊的匿名内部类,语法更简洁
允许吧函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递
1.2语法
<函数式接口> <变量名> = (参数1,参数2…) -> {
// 方法体
};
Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分:
- 左侧:(参数1,参数2…)表示参数列表
- 右侧:{ }内部是方法体
注意事项:
- 形参列表的数据类型会自动推断。
- 如果形参列表为空,只需保留() 。
- 如果形参只有1个,()可以省略,只需要参数的名称即可。
- 如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句。
- [Lambda不会生成一个单独的内部类文件。
二、方法的引用
2.1概念
方法引用来自官方的说明
You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it's often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.
你使用lambda表达式创建匿名方法。 但是,有时lambda表达式除了调用现有方法外什么也不做。 在这种情况下,通常更容易按名称引用现有方法。 方法引用使你可以执行此操作; 它们是紧凑的,对于已经具有名称的方法lambda表达式更易于阅读。
- 方法引用是Lambda表达式的一种简写形式。
- 如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。
2.2语法
方法引用符 -----> “::”
双冒号::
为方法引用符,而它所在的表达式被称为方法引用。如果Lambda表达式赋值的方法已经在某个类中有具体的实现,那么则可以通过双冒号来引用该方法作为Lambda表达式的替代者。
案例:
public interface Actor {
/**
* 演员表演节目
*/
void perform(String item);
}
public class ActorTest {
public static void main(String[] args) {
// 使用匿名内部类实现
Actor actor1 = new Actor() {
@Override
public void perform(String item) {
System.out.println(item);
}
};
actor1.perform("跳舞");
System.out.println("---------------------");
// 使用lambda的形式
Actor actor2 = item -> System.out.println(item);
actor2.perform("唱歌");
System.out.println("--------------------");
// 方法引用
/*
这个接口方法的实现,本质来说就是调用了System类中out对象的println方法
JDK8新特性 - 方法引用符 :: 双冒号
语法规则:
成员方法引用: 对象名::方法名
静态方法引用: 类名::方法名
this this::方法名
supper supper::方法名
*/
Actor actor = System.out::println; // 成员方法引用
actor1.perform("弹钢琴");
}
}
分析:
上面的示例中,Lambda表达式的作用就是调用System.out
中的println(String msg)
方法,这个方法已经有具体的实现。
使用方法引用进一步简化代码
总结:
方法引用与Lambda表达式一样,只能应用于函数式接口。方法有静态方法、成员方法和构造方法之分,方法引用因此也分为静态方法引用、成员方法引用和构造方法引用
2.3静态方法引用
语法:
类名::方法名
案例:
// 计算器接口
public interface Calculator {
int calculate(int a,int b);
}
public class MathUtil {
public static int add(int a, int b){
return a + b;
}
public static int minus(int a, int b){
return a - b;
}
public static int multiply(int a, int b){
return a * b;
}
public static int divided(int a, int b){
return a / b;
}
}
public class CalculatorTest {
public static void main(String[] args) {
// Calculator c = new Calculator() {
// @Override
// public int calculate(int a, int b) {
// return MathUtil.minus(a, b);
// }
// };
// Calculator c = (int a, int b) -> {
// return MathUtil.minus(a, b);
// };
// Calculator c = (a, b) -> MathUtil.minus(a, b);
Calculator c = MathUtil::minus;
int result = c.calculate(1, 10);
System.out.println(result);
Calculator c1 = MathUtil::multiply;
int result1 = c1.calculate(1, 10);
System.out.println(result1);
}
}
//
public class CalculatorTest {
public static void main(String[] args) {
// 使用匿名内部类实现
Calculator c1 = new Calculator() {
@Override
public int calculate(int a, int b) {
return Integer.sum(a,b);// 求和
}
};
System.out.println("c1 : " + c1.calculate(1,2));
System.out.println("---------------------");
// 这里接口的实现只是调用了Integer类提供的静态方法sum,可以实现代码简化
// 使用lambda实现
Calculator c2 = (a, b) -> Integer.sum(a, b);
System.out.println("c2 : " + c2.calculate(3,4));
System.out.println("---------------------");
// 使用方法引用
Calculator c3 = Integer::sum;
System.out.println("c3 : " + c3.calculate(5,6));
System.out.println("---------------------");
// 比较器接口 Comparator
// 匿名内部类实现
Comparator<Double> comparator1 = new Comparator<Double>() {
@Override
public int compare(Double o1, Double o2) {
return Double.compare(o1,o2); // o1大于o2返回1 ,o1小于o2返回-1,等于比较复杂
/*
// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
*/
}
};
System.out.println("小于的情况: " + comparator1.compare(1.0,10.0));
System.out.println("大于的情况: " + comparator1.compare(6.0,5.0));
System.out.println("等于的情况: " + comparator1.compare(1.0,1.0));
System.out.println("---------------------");
// 使用方法引用
Comparator<Double> comparator2 = Double::compare;
System.out.println("小于的情况: " + comparator2.compare(1.0,10.0));
System.out.println("大于的情况: " + comparator2.compare(6.0,5.0));
System.out.println("等于的情况: " + comparator2.compare(0.0,0.0));
}
}
2.4成员方法引用
语法:
对象名:: 方法名
案例:
public interface Printable {
// 打印信息
void print(String msg);
}
public class StandardConsole {
public void print(String msg){
System.out.println("控制台打印" + msg);
}
}
public class PrintableTest {
public static void main(String[] args) {
// 匿名内部类实现
Printable p1 = new Printable() {
@Override
public void print(String msg) {
new StandardConsole().print(msg);
}
};
p1.print("方法实现1");
// 方法引用
Printable p2 = new StandardConsole()::print;
p2.print("成员方法引用实现2");
}
}
2.5this引用成员方法
语法:
this::方法名
案例:
// 照相机解耦
public interface Camera {
// 拍照方法
void takePhoto(String name);
}
// 人类
public class Person {
public void dance(){
System.out.println("跳舞");
}
public void sing(String s){
System.out.println(s);
}
public void run(){
System.out.println("跑步");
}
public void takePhoto(String name){
System.out.println("给" + name + "拍照");
}
public void travel(String name) {
Camera c1 = new Camera() {
@Override
public void takePhoto(String name) {
Person.this.takePhoto(name);
}
};
// 成员方法引用
Camera c2 = Person.this::takePhoto;
// this方法引用
Camera c3 = this::takePhoto;
c3.takePhoto(name);
}
}
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
p.travel("中国");
}
}
2.6super引用父类成员方法
语法:
super::方法名
案例:
public interface Customer {
// 交流业务
void communicateBusiness();
}
public class SoftEngineer {
public void analysBusyness(){
System.out.println("软件工程师分析业务");
}
}
public class JavaProgammer extends SoftEngineer{
// 重写方法
public void analysBusyness(){
System.out.println("java程序员与客户交流业务");
}
// Java程序员与客户交流业务
// 匿名内部类形式
public void communicateWithCustomer() {
Customer c1 = new Customer() {
@Override
public void communicateBusiness() {
JavaProgammer.super.analysBusyness();
}
};
// super方法引用
Customer c2 = super::analysBusyness;
c2.communicateBusiness();
}
}
public class JavaProgammerTest {
public static void main(String[] args) {
JavaProgammer javaProgammer = new JavaProgammer();
javaProgammer.communicateWithCustomer();
javaProgammer.analysBusyness();
}
}
2.7构造方法引用
语法:
类名::new
案例:
public class Student {
private String name;
private String sex;
public Student() {
}
public Student(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
public interface StudentBuilder {
Student build(String name,String sex);
}
public class StudentBuilderTest {
public static void main(String[] args) {
StudentBuilder builder1 = new StudentBuilder() {
@Override
public Student build(String name, String sex) {
return new Student(name,sex