先来看一个简单的接口,通过学生的学号获取姓名,假设接口是这样子的。

package help.mygod.java8;

public interface IStudent {

    String getName(String id);

}

简单吧,现在如果我们要用getName,有几种方法呢,首先想到的应该是写一个类Student实现IStudent,或者用匿名内部类,又或者用java8的λ表达式。所以代码如下,

package help.mygod.java8;

public class Main {

    public static void main(String[] args) {
        // 1,实现接口
        IStudent student = new Student();
        printName(student, "007");
        // 2,匿名内部类
        printName(new IStudent() {

            @Override
            public String getName(String id) {
                if ("007".equals(id))
                    return "William";
                else
                    return "Moss";
            }
        }, "007");

        // 3,λ表达式
        printName(id -> {
            if ("007".equals(id))
                return "William";
            else
                return "Moss";
        }, "007");

    }

    public static void printName(IStudent student, String id) {
        System.out.println(student.getName(id));
    }
}

仔细对比一下匿名内部类和λ表达式,是不是觉得λ表达式就去掉了类的外壳,然后方法简写了一下呢?事实就是这样的,λ表达式就是接口里的唯一未实现方法,语法是这样子的,(参数列表),箭头->,函数体。然后只有一的时候可以省略,一个参数可以省略小括号,一句函数体可以省略大括号,哦,对了 一句函数体的话,return也可以省略。所以只有一的时候省略。

λ表达式究竟是个什么玩意呢? 刚刚说了是接口里的唯一未实现方法,这句话挺拗口的,我们来看看是怎么一回事。先看printName,λ表达式传进来,我们的方法是用了一个接口类IStudent来接收的,所以它是一个接口。实际上这样调用也是可以的。

package help.mygod.java8;

public class Main {

    public static void main(String[] args) {

        IStudent student = id -> {
            if ("007".equals(id))
                return "William";
            else
                return "Moss";
        };

        printName(student,"007");
    }

    public static void printName(IStudent student, String id) {
        System.out.println(student.getName(id));
    }
}

然后它又是一个方法,那它怎么知道是接口的哪一个方法呢。实现类或者匿名内部类都可以通过方法名,参数类型之类的找出,而λ表达式又没方法名,参数类型也是没有的,这按传统的方法就没辙了。所以java8给了一个简单粗暴的办法,就找接口里面唯一没有实现的方法。所以如果接口里面有多个未实现方法,那就会编译报错了。比如在接口里随便加上

package help.mygod.java8;

public interface IStudent {

    String getName(String id);

    void printName();
}

然后就会报 The target type of this expression must be a functional interface,所以为了无意间忘记了这个是λ表达式接口(或者叫函数式接口),推出了一个注解@FunctionalInterface,就是说这个接口只能有一个未实现方法,如果不是,就会提示出错的。

然而毕竟接口有时需要多个方法的,这下怎么办呢?别急,java8推出了一个default,就是在接口中也可以有具体的方法,而且这个方法在子类也是可以重写的。然后把接口改写如下就可以了。

package help.mygod.java8;

@FunctionalInterface
public interface IStudent {

    String getName(String id);

    default void printName(){
        System.out.println("I student");
    }
}

想一下,java8的接口是不是要逆天了,哈哈,今天先说到这吧。