从Java匿名内部类深入到JDK8的Lombda表达式

Lombda表达式是用简洁的代码创建只有一个抽象方法的接口(函数式接口),在这之前我们都是用匿名内部类创建的。

匿名内部类
先看例子

  1. interface Dog{
  2. void getColor();
  3. void getName();
  4. }
  5. class RedDog implements Dog{
  6. void getColor(){
  7. System.out.pringln("我是Red");
  8. }
  9. void getName(){
  10. System.out.pringln("我是Dog");
  11. }
  12. }
  13. public class Test{
  14. //用Dog作为参数
  15. public void testDog(Dog d){
  16. d.getColor();
  17. }
  18. public static void main(String [] args){
  19. Test t=new Test();
  20. RedDog dog=new RedDog();
  21. t.testDog(dog);
  22. }
  23. }

通常我们要调用testDog方法时,我们就要传入Dog的实现类,于是我们实现了RedDog,但是我们有时候RedDog只用一次,而然还要创建RedDog不是很麻烦吗?于是可以用匿名内部类。

  1. interface Dog{
  2. void getColor();
  3. void getName();
  4. }
  5. public class Test{
  6. //用Dog作为参数
  7. public void testDog(Dog d){
  8. d.getColor();
  9. }
  10. public static void main(String [] args){
  11. Test t=new Test();
  12. t.testDog(new Dog(){
  13. void getColor(){
  14. System.out.pringln("我是Red");
  15. }
  16. void getName(){
  17. System.out.pringln("我是Dog");
  18. }
  19. });
  20. }
  21. }

是不是感觉很熟悉,对的,我们经常再线程那边的run方法用到,对此我们可以得出,

匿名内部类主要用在只要用一次的时候,
其次他不能再次时抽象方法,要实现所有接口的方法,当然也可以实现接口的默认方法(JDK8) ,因为我们要创建对象,
然后他不能自定义构造方法,因为没有类名,所有只能用默认的构造方法
注意:在JDK8之前,我们在使用匿名内部类方法局部变量时,我们设置为final,但是JDK8后会自动给我们加上。

  1. interface Dog{
  2. void getName();
  3. }
  4. public class Test{
  5. //用Dog作为参数
  6. public void testDog(Dog d){
  7. d.getColor();
  8. }
  9. public static void main(String [] args){
  10. String name="redDog"
  11. Test t=new Test();
  12. t.testDog(new Dog(){
  13. void getName(){
  14. //在jdk8之前会报错,因为name没被final修饰
  15. System.out.pringln(name);
  16. }
  17. });
  18. }
  19. }

Lombda表达式
Lombda表达式是用简洁的代码创建只有一个抽象方法的接口(函数式接口)实现类的对象,如:
匿名内部类

  1. interface Dog{
  2. void getName();
  3. }
  4. public class Test{
  5. //用Dog作为参数
  6. public void testDog(Dog d){
  7. d.getColor();
  8. }
  9. public static void main(String [] args){
  10. Test t=new Test();
  11. t.testDog(new Dog(){
  12. void getName(){
  13. System.out.pringln("我是Dog");
  14. }
  15. });
  16. }
  17. }

Lombda表达式

  1. interface Dog{
  2. void getName();
  3. }
  4. public class Test{
  5. //用Dog作为参数
  6. public void testDog(Dog d){
  7. d.getColor();
  8. }
  9. public static void main(String [] args){
  10. Test t=new Test();
  11. t.testDog(()->{
  12. System.out.pringln("我是Dog");
  13. }
  14. });
  15. }
  16. }

从这段代码来看,使用Lombda来代替匿名匿名类创建对象时,将代替的是匿名内部类的方法体,所以Lombda只能代替一个方法体。于是我们可以得出lambda要的只有一个抽象方法的接口,不然实现不了其他方法,于是还是抽象类不能创建对象。
Lombda表达式的组成

() 这个是形参的部分,由于getName方法不用参数。就是一个括号就行
-> 必须要用英文的-和>组成
{} 这个是方法要实现的代码快
Lombda表达式几种简写的方式
1.当只有一个参数时,我们可以去掉()

  1. interface Dog{
  2. void getName(String name);
  3. }
  4. public class Test{
  5. //用Dog作为参数
  6. public void testDog(Dog d){
  7. d.getColor();
  8. }
  9. public static void main(String [] args){
  10. Test t=new Test();
  11. String name="dog";
  12. t.testDog(name->{
  13. System.out.pringln("我是Dog");
  14. }
  15. });
  16. }
  17. }

2.当代码块只有一句时,可以去掉{}

  1. interface Dog{
  2. void getName(String name);
  3. }
  4. public class Test{
  5. //用Dog作为参数
  6. public void testDog(Dog d){
  7. d.getColor();
  8. }
  9. public static void main(String [] args){
  10. Test t=new Test();
  11. String name="dog";
  12. t.testDog(name->System.out.pringln("我是Dog");
  13. });
  14. }
  15. }

3.当代码块只有一句时,改代码的值作为返回值,不用 return;

  1. interface Dog{
  2. String getName(String name);
  3. }
  4. public class Test{
  5. //用Dog作为参数
  6. public void testDog(Dog d){
  7. d.getColor();
  8. }
  9. public static void main(String [] args){
  10. Test t=new Test();
  11. String name="dog";
  12. t.testDog(name->"我是"+name
  13. });
  14. }
  15. }

函数式接口
上面说到只有一个抽象方法的接口是函数式接口,可以用Lombda表达式,那么JDK8中有很多都是这种的,如:Runable等等,其实可以分这几类:
XxxFunction:这种接口通常有个apply抽象方法,主要是用来对参数的处理转换,而然处理逻辑使用lambda表达式实现。最后返回值
XxxConsumer:这种接口通常有个accept抽象方法,主要用来对参数的处理转换,但是不返回值
XxxPredicate:这种接口通常包含一个test抽象方法,对参数的某种判断,返回boolean值,逻辑用lambda表达式实现
XxxSupplier:这种接口有个getAsXxx抽象方法,该方法不用参数,按照某种算法返回值

有了这些基础可以接着看这边文章深入了解lambda表达式JDK8特性一之Lambda表达式