Lambda表达式
Java 8的一个大亮点是引入Lambda表达式(匿名函数),使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。可以使用Lambda语法来代替匿名的内部类,代码不仅简洁,而且还可读。
函数式接口
Java8的新引入,包含函数式的设计,接口都有**@FunctionalInterface的注解**。就像这个注解的注释说明一样,它注解在接口层面,且注解的接口要有且仅有一个抽象方法
Lambda表达式学习
直接看代码,我就用多线程的代码举栗子一步一步看Lambda表达式的推导:
看代码:
不使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
new Thread(new Runnable() {
@Override
public void run() {
System
.out
.println("断剑重铸之日,骑士归来之时");
}
}).start();
}
}
运行结果:

这个代码相信小伙伴们很容易看懂。
接下来是使用Lambda表达式了,首先我们看下Lambda表达式的格式:
()->->:被称为Lambda操作符。左边:Lambda形参列表(接口中的抽象方法的形参列表)右边:Lambda体(重写接口的抽象方法的方法体)
Lambda表达式的本质就是:作为接口的实例
使用Lambda表达式
public class TestLambda {
public static void main(String
[] args
) {
new Thread(() -> {
System
.out
.println("断剑重铸之日,骑士归来之时");
}).start();
}
这是Lambda表达式后的代码,基本上只保留的重写接口方法的方法体,
因为这个方法体中只有一句代码,所以可以把{}去掉。
使用Lambda表达式(最终版)
public class TestLambda {
public static void main(String
[] args
) {
new Thread(() -> System
.out
.println("断剑重铸之日,骑士归来之时")).start();
}
是不是强大到可怕?是不是简单到可怕?是不是清晰明了重点突出到可怕?这就是Lambda表达式的可怕之处,用极少的代码完成了之前一个类做的事情!能够代替实现函数式接口的匿名内部类。
关于Lambda的使用:
1、无参无返回值且只有一条执行语句:
这个就是上边那个例子
不使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
new Thread(new Runnable() {
@Override
public void run() {
System
.out
.println("断剑重铸之日,骑士归来之时");
}
}).start();
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
new Thread(() -> System
.out
.println("断剑重铸之日,骑士归来之时")).start();
}
运行结果是一样的:

2、有多条执行语句(不能省略{} ):
不使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
new Thread(new Runnable() {
@Override
public void run() {
System
.out
.println("断剑重铸之日,骑士归来之时");
System
.out
.println("时间不在于你拥有多少,而在于你怎样使用它");
}
}).start();
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
new Thread(() -> {
System
.out
.println("断剑重铸之日,骑士归来之时");
System
.out
.println("时间不在于你拥有多少,而在于你怎样使用它");
}).start();
}
}
2、只有1个参数无返回值:
不使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
Consumer
con1
= new Consumer() {
@Override
public void accept(String s
) {
System
.out
.println(s
);
}
};
con1
.accept("无形之刃,最为致命");
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
//数据类型可以省略,因为可以由编译器去推断
Consumer
con2
= (String s
) -> System
.out
.println(s
);
con2
.accept("无形之刃,最为致命");
//只有一个参数()也可以省略
Consumer
con3
= s
-> System
.out
.println(s
);
con2
.accept("无形之刃,最为致命");
}
}
3、有两个或两个以上的参数,且有返回值
使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
new Thread(() -> {
System
.out
.println("断剑重铸之日,骑士归来之时");
System
.out
.println("时间不在于你拥有多少,而在于你怎样使用它");
}).start();
}
}
不使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
Comparator
com1
= new Comparator() {
@Override
public int compare(Integer o1
, Integer o2
) {
return o1
.compareTo(o2
);
}
};
System
.out
.println(com1
.compare(12, 21));
}
}
使用Lambda表达式:
public class TestLambda {
public static void main(String
[] args
) {
Comparator
com2
= (o1
,o2
) -> {
return o1
.compareTo(o2
);
};
System
.out
.println(com2
.compare(6, 2));
//注意:return和{}要一起省略
Comparator
com3
= (o1
,o2
) -> o1
.compareTo(o2
);
System
.out
.println(com3
.compare(6, 2));
}
}
以上就是对Lambda表达式的基本的使用。
接下来简单了解一下方法引用
方法引用
方法引用是Lambda表达式的一个简化写法。所引用的方法其实是Lambda表达式的方法体的实现,其语法结构为:
ObjectRef
::methodName
左边可以是类名或者实例名,中间是方法引用符号”::”,右边是相应的方法名。
public class ReferenceTest {
public static void main(String
[] args
) {
Converter
converter
=new Converter() {
@Override
public Integer
convert(String from
) {
return ReferenceTest
.StringToInt(from
);
}
};
converter
.convert("120");
}
//函数式接口
@FunctionalInterface
interface Converter{
T
convert(F from
);
}
public static int StringToInt(String from
) {
return Integer
.valueOf(from
);
}
}
这时候如果用静态引用会使的代码更加简洁:
Converter
converter
= ReferenceTest
::StringToInt
;
converter
.convert("120");
方法引用我们可以把它看做是 仅仅调用特定方法的Lambda的一种快捷写法。
实例如下:
(Apple a
) -> a
.getWeight() Apple
::getWeight
() -> Thread
.currentThread().dumpStack() Thread
.currentThread()::dumpStack
(str
, i
) -> str
.substring(i
) String
::substring
(String s
) -> System
.out
.println(s
) System
.out
::println
方法引用可以分为三类:
指向静态方法:
(args
) -> ClassName
.staticMethod(args
)
//可以写成
ClassName
::staticMethod
指向实例对象的任意方法(arg0是ClassName类型的):
(arg0
, rest
) -> arg0
.instanceMethod(rest
)
//可以写成
ClassName
::instanceMethod
指向实例对象的属性的方法引用:
(args
) -> expr
.instanceMethod(args
)
//可以写成
expr
::instanceMethod