一、接口的默认方法
定义
接口不只是一个只能声明方法的地方,还可以在声明方法的时候,给方法一个默认的实现,而不需要实现类去实现其方法。默认方法用default关键字修饰,它默认就是public权限的。
特点
(1)所有的实现类都会自动继承接口中定义的默认方法;
(2)接口中的默认方法可以被实现类重写;
(3)在被调用时,实现类重写后的方法优先于默认方法;
(4)和1.8之前一样,在接口中仍然不允许定义普通的实现方法,接口任然会保持除这些新特性外的所有原有特性。
举例
package com.test.a;
public interface Base {
public default void f() {// only public,default,abstract
System.out.println("hello world1");
}
default void f2() {
System.out.println("hello world2");
}
public void f3();;// 必须不能有方法体
public static void f4() {// 必须要有方法体,即使方法体中没有具体的实现逻辑
System.out.println("hello world4");
}
}
package com.test.a;
public class Sub implements Base {
@Override
public void f3() {
System.out.println("hello world3");
}
public void f2() {//只可以时public,因为父类是public,子类不可以缩小父类的访问权限
System.out.println("hahahh");
}
}
package com.test.a;
public class Test {
public static void main(String args[]) {
Sub sub = new Sub();
sub.f();
sub.f2();
sub.f3();
Base.f4();// f4只可以Base来调用
}
}
1 hello world1
2 hahahh
3 hello world3
4 hello world4
为什么引入default方法?
(1)以前的接口中只要定义了方法,都需要在实现类中进行实现。即使是个空的实现,也必须写出来;但是在新特性中,添加了默认方法,就无需在实现类中再次实现了,除非想要再次实现,直接重写就可以了;
(2)为接口添加新的默认方法,是不会破坏原有接口的实现;
(3)不需要修改接口的实现类,就可以为接口添加新的方法实现;
(4)对于已经发布的版本,是无法在给接口添加新方法的同时而不影响已有的实现,因此引入了default。目的是为了解决接口的修改与已有的实现不兼容的问题。
5. 易错点
(1)如果一个类实现两个或两个以上接口,并且多个接口中包含统一默认方法,此时,编译器将报错。这种情况,我们必须让子类Override该方法,否则无法编译通过。
public interface Base {
public default void f() {// only public,default,abstract
System.out.println("hello world1");
}
default void f2() {
System.out.println("hello world2");
}
public void f3();;// 必须不能有方法体
public static void f4() {// 必须要有方法体,即使方法体中没有具体的实现逻辑
System.out.println("hello world4");
}
}
package com.test.a;
public interface Base2 {
default void f2() {
System.out.println("Base2 hello world2");
}
}
上面就会提示要么重写Base的f2方法,要么重写Base2的f2方法;
(2)如果是一个接口继承了另外一个接口,2个接口中也包含相同的默认方法,那么继承接口的版本具有更高的优先级。比如A继承了B接口,那么优先使用A接口里面的default方法;
(3)通过使用super,可以显式的引用被继承接口的默认实现,语法如下:InterfaceName.super.methodName()。
package com.test.a;
public interface Base {
public default void f() {// only public,default,abstract
System.out.println("hello world1");
}
default void f2() {
System.out.println("hello world2");
}
public void f3();;// 必须不能有方法体
public static void f4() {// 必须要有方法体,即使方法体中没有具体的实现逻辑
System.out.println("hello world4");
}
}
package com.test.a;
public class Sub implements Base {
@Override
public void f3() {
System.out.println("hello world3");
}
public void f2() {
Base.super.f2();
}
}
1 hello world1
2 hello world2
3 hello world3
4 hello world4
静态方法
定义
和普通的静态方法定义一样
特点
(1)只能是静态方法所属的类来调用(即使是子类等等都不行)
(2)**必须有方法体,**即使方法体中没有具体实现;区别于上面的普通方法必须不能有方法体;
(3)实现接口的类或者子接口不会继承接口中的静态方法。static不能和default同时使用。在java8中很多接口中都增加了静态方法
用途
(1)因为是静态方法,它是不能被实现类重写的(否则编译异常:This static method cannot hide the instance method from Object),因此,它可以用来提供防止实现类不良重写的保障;
(2)常常可以作为工具型的方法,比如:空值检查,集合类排序等等;
(3)比如可以将java.util.collections类改成接口(eg:Collection) 中的静态方法,进行调用;