27. 接口的默认方法
这句话在JAVA8之前是对的,在JAVA8之后就错了
传统的理解是接口只能是抽象方法。但是程序员们在使用中,发现很不方便,实现接口必须重写所有方法,很麻烦。所以java设计者妥协了,在java8中,支持default和static方法,这样,实现接口时,可以选择不对default修饰的方法重写。
概念:
- 接口提供一个默认实现的方法,并且不强制实现类重写此方法
接口提供一个默认实现的方法,并且不强制实现类重写此方法
默认方法使用default关键字来修饰
default修饰方法只能在接口中使用,在接口种被default标记的方法为普通方法,可以直接写方法体。
接口中支持定义静态方法,将关键字换成static即可
如果是Java 7,那么接口中可以包含的内容有:
- 常量
- 抽象方法
如果是Java 8,还可以额外包含有: 3. 默认方法default 4. 静态方法static
如果是Java 9,还可以额外包含有: 5. 私有方法
接口的默认方法
从Java 8开始,接口里允许定义默认方法。 格式:
public default 返回值类型 方法名称(参数列表) {
方法体
}
备注:接口当中的默认方法,可以解决接口升级的问题。
接口的静态方法
从Java 8开始,接口里允许定义静态方法。 格式:
从Java 8开始,接口里允许定义静态方法。
格式:
public interface InterfaceA {
/**
* 静态方法
*/
static void showStatic() {
System.out.println("InterfaceA++showStatic");
}
}
注意,实现接口的类或者子接口不会继承接口中的静态方法
特点
- 默认方法可以不强制重写,并且在一个类继承接口后可以直接使用接口中的默认方法
- 继承类可以直接使用接口中的static方法,也可以创建对象后使用接口中的default方法
interface InterfaceA // 定义一个接口
{
default public void otherprint() // 带方法体的默认方法
{
System.out.println("print default1 methods InterfaceA!");
}
}
class subClass implements InterfaceA //子类InterfaceAB实现接口InterfaceA
{
}
public class Interfacedefault
{
public static void main(String[ ] args)
{
subClass subObj = new subClass( ); //实例化子类对象
subObj.otherprint( ); //调用接口中的默认方法
InterfaceA InterfaceAobj = new subClass(); // 实例化子类对象,赋值给一个接口引用
InterfaceAobj.otherprint( ); //调用接口中的默认方法
}
}
输出:
注意如果是static静态方法,类继承接口后不可以直接用,也就是上方的default改为static 就会出错
多个接口中存在相同默认方法
当一个类实现多个接口时,若多个接口中存在相同默认方法(方法名、参数、返回值相同),此时实现类必须要重写默认方法,否则编译错误
Java中只能继承一个类,但是可以实现多个接口,当多个接口中有同一个方法时,以前是没问题的,因为实现类必须重写方法。但现在,当多个接口中有同一个用default修饰的方法时,就无法判断到底实现的是哪个接口的方法。这种情况下,就必须重写方法。
重写有两种实现方法:
- 实现类中自己重写默认方法
- 实现类使用super关键字指定使用哪个接口的默认方法
interface TestInterface1{ //定义接口1
default void test() {
System.out.println("TestInterface1");
}
}
interface TestInterface2{ //定义接口2
default void test(){
System.out.println("TestInterface2");
}
}
方法1
class Test implements TestInterface1, TestInterface2
{
@Override
public void test()
{
System.out.println("这是重写的方法");
}
}
public class test{
public static void main(String[ ] args)
{
Test TestsubObj = new Test ( ); //实例化子类对象
TestsubObj .test( ); //调用接口中的默认方法
}
}
方法2
public class Test implements TestInterface1, TestInterface2
{
@Override
public void test()
{
// 调用TestInterface1接口的默认test()方法
TestInterface1.super.test();
}
}
public class App{
public static void main(String[ ] args) {
Test TestsubObj = new Test ( ); //实例化子类对象
TestsubObj .test( ); //调用接口中的默认方法
}
}
当然,如果A和B的默认方法不同, 实现类C则会隐式继承了两个默认方法
如果子类继承父类,父类中有A方法,该子类同时实现的接口中也有A方法,那么子类会继承父类的b方法而不是继承接口中的b方法 子类优先继承父类的方法, 如果父类没有相同签名的方法,才继承接口的默认方法。
interface InterfaceA // 定义一个接口
{
default public void test() // 带方法体的默认方法
{
System.out.println("print default1 methods InterfaceA!");
}
}
类B
public class B {
public void test() {
System.out.println("print Class B");
}
}
类Test 继承类B和接口A class Test extends B implements InterfaceA{ }
新建一个Test对象,调用test方法 为类B中的方法。
实现类中如果重写了接口的default 默认方法 那么 实例化子类对象,赋值给接口引用之后,还是使用重写的默认方法
一个实现了接口的类的对象赋给接口的引用, “一个接口,多个方法”,展示了Java的动态多态性。 java可以父类引用子类,体现了java的多态性,但是不能子类引用父类,可以从上往下,不可以从下往上
interface InterfaceA // 定义一个接口
{
default void otherprint() // 带方法体的默认方法
{
System.out.println("print default1 methods InterfaceA!");
}
}
class SubClass implements InterfaceA //子类InterfaceAB实现接口InterfaceA
{
public void otherprint() // 带方法体的默认方法
{
System.out.println("实现类重写的方法");
}
}
public class trival{
public static void main(String[ ] args) {
SubClass subObj = new SubClass( ); //实例化子类对象
subObj.otherprint( ); //调用接口中的默认方法
InterfaceA InterfaceAobj = new SubClass(); // 实例化子类对象,赋值给一个接口引用
InterfaceAobj.otherprint( ); //调用接口中的默认方法
}
}
两次打印都是
实现类重写的方法
实现类重写的方法