Java8新特性:默认方法详解

什么是默认方法

 

Java8 中的默认方法是针对接口添加的新特性,它是指接口可以直接对方法进行实现,实现方式很简单,直接在方法定义处添加 default 关键字即可,如下所示。

 

public interface MyInterface {
    default void test(){
        System.out.println("这是一个默认方法...");
    }
}

 

虽然接口中可以直接定义方法,但是调用该方法还是需要实例化对象,所以仍然需要创建接口的实现类,区别在于实现类不必对默认方法进行具体实现,如下所示。

 

public class MyImplements implements MyInterface {
}

 

根据实现类创建接口的实例化对象,调用默认方法,如下所示。

 

public class Test {
    public static void main(String[] args) {
        MyInterface myInterface = new MyImplements();
        myInterface.test();
    }
}

 

运行结果如下图所示。

 

 

同时我们也可以在实现类中对方法进行实现,从而覆盖接口中的默认方法,如下所示。

 

public class MyImplements implements MyInterface {
    @Override
    public void test() {
        System.out.println("这是实现类的方法...");
    }
}

 

再次运行测试方法,结果如下图所示。

 

 

当然也可以通过匿名类的方式对默认方法进行覆盖,如下所示。

 

public class Test {
    public static void main(String[] args) {
        MyInterface myInterface = new MyInterface() {
            @Override
            public void test() {
                System.out.println("这是匿名类方法...");
            }
        };
        myInterface.test();
    }
}

 

运行结果如下图所示。

 

 

了解完默认方法的概念和使用,接下来我们说一说为什么要使用默认方法。

 

面向接口编程可以实现代码的解耦合,从而提高程序的扩展性,但是这种方式也存在明显的不足,当对接口进行修改时,所有的实现类都要同步修改,这样就非常麻烦,使用默认方法可以解决这一问题,只需要修改接口的默认方法即可,实现类不需要进行处理。

 

 

默认方法在 Java8 中的实际应用

 

Java8 针对集合操作提供了一个新的方法 forEach,并将其定义在 Iterable 接口中,如果没有默认方法机制,那么 Java8 中所有的 Iterable 实现类都需要修改,接口和实现类高度耦合,默认方法可以完美地解决这一问题,只需要将 forEach 定义成默认方法即可,源码如下图所示。

 

 

 

默认方法的继承

 

默认方法支持继承,即子接口可以继承父接口中的默认方法,如下所示。

 

/**
 * 父接口
 */
public interface MyInterface {
    default void test(){
        System.out.println("这是一个默认方法...");
    }
}

/**
 * 子接口
 */
public interface MyInterfaceB extends MyInterface {
}

/**
 * 实现类
 */
public class MyImplements implements MyInterfaceB {
}

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        MyInterfaceB myInterfaceB = new MyImplements();
        myInterfaceB.test();
    }
}

 

运行结果如下图所示。

 

 

同时子接口也可以完成对父接口默认方法的重写,如下所示。

 

/**
 * 父接口
 */
public interface MyInterface {
    default void test(){
        System.out.println("这是一个默认方法...");
    }
}

/**
 * 子接口
 */
public interface MyInterfaceB extends MyInterface {
    @Override
    default void test() {
        System.out.println("这是子接口的默认方法...");
    }
}

/**
 * 实现类
 */
public class MyImplements implements MyInterfaceB {
}

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        MyInterfaceB myInterfaceB = new MyImplements();
        myInterfaceB.test();
    }
}

 

运行结果如下图所示。

 

 

 

接口多实现场景下默认方法冲突的解决方案

 

如果两个不同的接口中定义同名的默认方法,创建一个实现类来同时实现这两个接口,就会出现问题,代码如下所示。

 

/**
 * 接口1
 */
public interface Run {
    default void test(){
        System.out.println("跑起来了...");
    }
}

/**
 * 接口2
 */
public interface Fly {
    default void test(){
        System.out.println("飞起来了...");
    }
}

public class MyImplements implements Run,Fly {
}

 

异常信息如下图所示。

 

 

MyImplements 无法区分两个默认方法,此时需要在实现类中通过 super 关键字来指定调用哪个接口的默认方法,如下所示。

 

public class MyImplements implements Run,Fly {
    public void test(){
        Fly.super.test();
    }
}

 

同时也可以在实现类中对方法进行重新定义,覆盖接口的默认方法,如下所示。

 

public class MyImplements implements Run,Fly {
    public void test(){
        System.out.println("MyImplements...");
    }
}

 

 

 

静态默认方法

 

默认方法也可以定义为静态,直接通过接口调用,具体操作如下所示。

 

public interface MyInterface {
    static void staticTest(){
        System.out.println("这是一个静态默认方法...");
    }
}

public class Test {
    public static void main(String[] args) {
        MyInterface.staticTest();
    }
}

 

运行结果如下图所示。

 

原文:https://mp.weixin.qq.com/s/GEEyoIyMDrBsPDp1ma9yoQ

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值