先来看一个简单的接口,通过学生的学号获取姓名,假设接口是这样子的。
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的接口是不是要逆天了,哈哈,今天先说到这吧。