一、允许给接口定义默认方法和静态方法
那么问题来了,
1、给接口定义的默认方法必须要用default关键字修饰,它是被定义为非抽象方法的,所以必须有方法体,即必须有方法的具体实现
(1)如果是一个子类既继承了父类同时又实现了带有默认方法的接口,而父类和接口有相同的方法,子类应该是选择哪一个执行呢?实践是检验真理的唯一标准,通过代码来寻找答案吧。
定义一个带默认方法的接口MyInterface:
定义一个父类Father:
定义一个子类Son:
执行结果如上图,所以这种情况下,子类会选择来自父类的方法。
(2)如果同时实现了有相同默认方法的多个接口,这个时候实现类又会如何选择呢?
还是看代码:
另一个接口的定义如下OtherInterface:
实现类报错了Son:
错误描述是:Duplicate default methods named greeting with the parameters () and () are inherited from the types OtherInterface and MyInterface
所以这种情况下实现类必须重写该方法。
正确实现如下:
2、静态方法必须要用static修饰,并且也是必须定义为非抽象方法的。
这里有必要解释一下在Java8以前接口方法不能定义为静态方法是什么含义。因为在Java8以前,接口中的方法都是抽象的,而静态方法是类方法,是不需要通过创建对象而通过类名直接调用的,抽象方法是没有方法体的,所以就没有办法执行了,所以也就不该能够被定义为静态方法了。
二、增加了函数式接口:有且仅有一个抽象方法的接口,但是可以有其他的非抽象方法(比如说默认方法和静态方法,因为默认方法和静态方法都不是抽象方法,正如新特性1中描述的那样)。还可以给接口添加@FunctionalInterface注解(是的,这里说的是可以而不是必须,所以@FunctionalInterface是可写可不写的),这样编译器如果发现接口标注了这个注解,有超过一个抽象方法或者没有定义抽象方法都会报错。
如下是错误的函数式接口的定义:
没有定义抽象方法:
定义了不止一个抽象方法:
以上两种错误的描述都是
Invalid '@FunctionalInterface' annotation; MyFunctionalInterface<T> is not a functional interface
这是使用了@FunctionalInterface来标识函数式接口的好处。
正确地定义一个函数式接口的例子如下:
三、引用了Lambda表达式
Lambda表达式的学习,它是如何写的?以及为什么要引入Lambda表达式,或者说引入它的意义又是什么?这些问题值得思考。
1、首先来了解Lambda表达式
Lambda表达式的语法格式是:
(parameters) -> expression
或
(parameters) ->{ statements; }
Lambda表达式有如下特征:
1)可选类型声明:参数类型可先可不写,如果不写,编译器会统一识别参数值
2)可选的参数圆括号:多个参数需要定义圆括号但一个参数可以不需要定义圆括号
3)可选的大括号:如果主体(expresstion/statements)只有一个语句,可以不需要用大括号
4)可选的return关键字:如果只有一个返回值表达式则可以省略掉return关键字
注意:
1)如果要给Lambda表达式的返回值赋值,返回值必须赋值给一个函数式接口,也就是说可以理解成整个Lambda表达式的返回值类型是一个函数式接口类型。
2)Lambda表达式可以作为方法的参数
3)Lambda表达式的常用场景是代替匿名内部类。
4)lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
5)在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
Java8新特性官网介绍:
http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html