• 浅析Java8中default关键字


    摘要:介绍Java8新增关键字default,它用于在接口中标记方法为默认方法和编写实现逻辑,方便通过新增方法重构接口,而无需修改所有实现类,目的在于兼容接口已有实现类。

    综述

      default关键字:是在java 8中引入的新概念,也可称为Virtual extension methods——虚拟扩展方法与public、private等都属于修饰符关键字,与其它两个关键字不同之处在于default关键字大部分都用于修饰接口。default修饰方法时只能在接口类中使用,在接口中被default标记的方法可以直接写方法体,而无需修改所有实现了此接口的类。

      这打破了Java之前版本对接口的语法限制。之前的版本里 interface 中的方法必须是抽象方法,不能有方法体。现在可以添加 interface 内方法,只需要在方法的前面加一个 default 关键字,表示属于接口内部默认存在的方法,但是,实现类中可以重写其实现,也可以不重写。在调用default修饰的方法时,如果没有匹配的实现类实现它,就执行接口类中定义的默认实现逻辑;否则,执行实现类中的逻辑。

    default的前世今生

      之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改该接口的全部实现类。例如,java8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进了默认方法。他们的目的是为了解决实现接口的缺陷问题(就是如果想修改接口时,所有实现了该接口的类都需要去修改)。

      通俗地讲,不使用default定义方法的话,该interface的实现类都必须重写所有的抽象方法,但是,在实现含有default方法的接口时,可以直接使用接口的default方法,也可以在个别实现类中重写接口中的default方法从而实现自己的业务逻辑。

    如何使用default关键词

      实现类会继承接口中的default方法。创建一个person类, 使用default修饰该方法:

    public interface Person {
        default String getName(){
            return "我是默认姓名";
        }
        default String getId(){
            return "我是默认ID";
        }
    }
    

      实现该接口的类不需要去实现默认方法,也可以实现,我们实现其中的一个,看看效果:

    @Service
    public class Student implements Person {
        
        @Override
        public String getId() {
            return "32";
        }
        public static void main(String[] args) {
            Student student = new Student();
            System.out.println(student.getName());
            System.out.println("重写接口类的默认方法,则结果由实现类决定:");
            System.out.println(student.getId());
        }
    }
    

      执行main方法进行验证,运行结果如下:

    我是默认姓名
    重写接口类的默认方法,则结果由实现类决定:
    32

      总而言之,当我们修改interface类的代码添加新功能时,必须要想尽办法兼容历史版本的代码,更何况这还是伟大的java,default方法应运而生。

    解决冲突

      如果集成的两个接口有default定义的同一个方法,例如

    public interface Person1 {
        default String getName(){
            return "我是另一个默认姓名";
        }
    }
    

      则编译器会报错。发生这种情况的原因是,实现类MyImplement即实现了接口Person又实现了接口Person1,恰巧两个接口中都定义可相同的默认方法。说白了就是编译器此时已经被干懵了,当我们在实现类Student中调用方法时,它不知道该去调用哪个接口类的默认方法。解决方法就是在实现类中实现该方法,重写接口实现。为什么要重写方法呢?是因为类在继承接口中的default方法时,不知道应该继承哪一个接口中的default方法。修改Student类后,代码如下:

    @Service
    public class Student implements Person, Person1 {
    
        @Override
        public String getName() {
            return "我是实现类中定义的姓名";
        }
    
        @Override
        public String getId() {
            return "32";
        }
    
        public static void main(String[] args) {
            Student student = new Student();
            System.out.println(student.getName());
            System.out.println("重写接口类的默认方法,则结果由实现类决定:");
            System.out.println(student.getId());
        }
    }
    

    类优先于接口

      创建一个实现类Student1,该实现类不仅继承了Student而且实现了Person1。

    public class Student1 extends Student implements Person1 {
    
        public static void main(String[] args) {
            Student1 student = new Student1();
            System.out.println(student.getName());
        }
    }
    

      问题:在实现类Student1中调用 getName() 方法,到底执行的是Student还是Person1中的方法?
      答:因为类优先于接口,所以将会执行Student中的方法。

    结束语

      本文介绍Java8新增关键字default,它用于在接口中标记方法为默认方法和编写方法体,方便通过新增方法重构接口,而无需修改所有实现类,目的在于兼容接口已有实现类。同时,演示了类优先于接口的规则。

      大家如果对于本文介绍的内容有不理解的地方,请在评论区留言。如果碰到【相关】问题也可以在评论区留言,和诸位互动交流。三人行必有我师,一起进步。大家可随意尽情享用本文啦!

    Reference

  • 相关阅读:
    第08组 Alpha冲刺(3/6)
    第08组 Alpha冲刺(2/6)
    第08组 Alpha冲刺(1/6)
    第08组 团队Git现场编程实战
    第08组 团队项目-需求分析报告
    网站是如何管理的
    拆机总结引发的组装指南
    计算机启动出现 Invalid Partition Table
    ARP 询问之 校级路由器的猫腻
    网络攻击形式备忘录
  • 原文地址:https://www.cnblogs.com/east7/p/15941584.html
Copyright © 2020-2023  润新知