前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java8新特性:默认方法详解

Java8新特性:默认方法详解

作者头像
南风
发布2019-07-29 19:15:58
4570
发布2019-07-29 19:15:58
举报
文章被收录于专栏:Java大联盟Java大联盟
Java大联盟

致力于最高效的Java学习

关注

什么是默认方法

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();
    }
}

运行结果如下图所示。

往期文章一览

1、Java8新特性:方法引用详解

2、Java8新特性:Lambda表达式详解

3、仿照源码,手写一个自定义 Spring MVC 框架

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java大联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档