匿名内部类与lambda表达式

2,413 阅读2分钟

lambda表达式是从匿名表达式演化而来,抽象而简洁高效。两者的使用方式相差无几,都是实现某个接口方法,但该接口有前提条件:有且仅有一个方法。若使用JDK版本为8及以上,则该方法不限于interface自带的static和default方法。

匿名内部类

特点

  • 必须继承一个父类或实现一个接口
  • 每次使用均创建新的匿名内部类对象

格式

new 父类构造器(参数列表)| 接口名() {... }

示例


public interface InnerInterface {
    
    public void test(String str);
    
    default String testDefault(String str) {
        return str.toUpperCase();
    }

    default Integer testDefault(Integer inte) {
        return inte * inte;
    }
    
    static Double testStatic(Double dou) {
        return dou * dou;
    }
    
}

class InnerInterfaceImpl {

    public static void main(String[] args) {
        InnerInterface inner = new InnerInterface() {
            @Override
            public void test(String str) {
                System.out.println("now is : " + str);
            }
        };
        inner.test(LocalDate.now().toString());
    }
    
}

输出为:now is : 2019-08-22

Lambda表达式

特点

  • 省略 new 接口名,简化为 () -> {... }

那么如何判断某个方法入参能使用Lambda表达式呢?其实很简单:只需判断该接口是否为函数是接口即可。

何为函数式接口?

特点

  • 要确保接口中有且仅有一个抽象方法即可:
 修饰符 interface 接口名 {
    public abstract 返回值类型 方法名称(可选参数信息);
    // 多个非抽象方法 如 default 及 static方法
    default 返回值 methodA(入参) {... }
    static 返回值 methodB(入参) {... }
 }
  • @FunctionalInterface注解
    该注解为JDK8专门为函数式接口而引入。该注解可定义于某个接口上,一旦使用,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

言归正传,我们还是接着聊Lambda表达式,在使用时有以下几点需注意:

  • Lambda表达式隐含return关键字。因此,当单个使用时,无需显示写return关键字
  • Lambda表达式为一个语句集合时,需显示添加return语句且用{ }将多个表达式括起来

示例如下:

// 返回大写的字符串,隐含return语句
(String s) -> s.toUpperCase();

// 总是返回hello world的无参方法
() -> "hello the world !"

// 多行表达式,用花括号括起来,并显示return
(int x, int y) -> {
    int z = x * y;
    return x + z;
}

上面的InnerInterface只有一个方法,拥有多个default及static方法,实际上就是一个函数式接口,因此我们换种写法,提炼下代码。

public interface InnerInterface {

    public void test(String str);

    default String testDefault(String str) {
        return str.toUpperCase();
    }

    default Integer testDefault(Integer inte) {
        return inte * inte;
    }

    static Double testStatic(Double dou) {
        return dou * dou;
    }

}

class InnerInterfaceImpl {

    public static void main(String[] args) {
        InnerInterface inner = new InnerInterface() {
            @Override
            public void test(String str) {
                System.out.println("first is : " + str);
            }
        };
        inner.test(LocalDate.now().toString());
        
        // 敲重点 第二种方式
        InnerInterface inner1 = (String now) -> System.out.println("second is : " + now);
        inner1.test(LocalDate.now().toString());
    }

}

输出为:
first is : 2019-08-22
second is : 2019-08-22