• Java8新特性之:接口的默认方法和静态方法


    一、默认方法(defult)

    接口默认方法的语法很简单,即:

    default 关键字 方法名(参数列表) { // 实现体 }

            默认方法主要优势是提供了一种扩展接口的方法,而不破坏现有代码。如果一个已经投入使用的接口需要扩展一个新的方法,在JDK8以前,我们必须再该接口的所有实现类中都添加该方法的实现,否则编译会出错。如果实现类数量很少且我们有修改的权限,可能工作量会少,但是如果实现类很多或者我们没有修改代码的权限,这样的话就很难解决了。而默认方法提供了一个实现,当没有显式提供时就默认采用这个实现,这样新添加的接口就不会破坏现有的代码。

            默认方法另一个优势是该方法是可选的,子类可以根据不同的需求而且经override或者采用默认实现。例如我们定义一个集合几口,其中有增、删、改等操作,如果我们的实现类90%都是以数组保存数据,那么我们可以定义针对这些方法给出默认实现,而对于其他非数组集合或者有其他类似业务,可以选择性复写接口中默认方法。(由于接口不允许有成员变量,所以本示例旨在说明默认方法的优势,并不具有生产可能性)具体参照如下代码:

     1 /**
     2      * 定义接口,并包含默认实现方法
     3     */
     4     public interface CollectionDemoInter {
     5     //增加默认实现
     6     default void addOneObj(Object object){
     7         System.out.println("default add");
     8     }
     9     //删除默认实现
    10     default void delOneObj(Object object){
    11         System.out.println("default del");
    12     }
    13     //更新默认实现
    14     default void updateOneObj(Object object){
    15         System.out.println("default del");
    16     }
    17     //接口定义需要实现方法
    18     String showMsg();
    19 }
    1 /**
    2      * 基于数组的集合实现类,增删改使用默认方法
    3     */
    4     public class Collection4Array implements  CollectionDemoInter {
    5         @Override
    6         public String showMsg() {
    7             return null;
    8         }
    9     }
     1 /**
     2      * 特殊集合,不允许删除元素
     3      */
     4     public class NodelCollection implements  CollectionDemoInter {
     5         @Override
     6         public String showMsg() {
     7             return null;
     8         }
     9         @Override
    10         public void delOneObj(Object object){
    11             System.out.println("none del");
    12         }
    13     }

    通过上述代码,大家可以很清楚的发现,如果在接口中定义默认方法,则子类不需要必须实现该默认实现,如果有特殊需求或者需要,则可以Override该实现。

    • 注意要点

    • 如果一个类实现两个或两个以上接口,并且多个接口中包含统一默认方法,此时,编译器将报错。这种情况,我们必须让子类Override该方法,否则无法编译通过。
    • 在所有的情况,类实现的优先级高于接口的默认实现,也就是先使用自己类中定义的方法或者是父类中的方法。
    • 如果是一个接口继承了另外一个接口,2个接口中也包含相同的默认方法,那么继承接口的版本具有更高的优先级。比如A扩展了B接口,那么优先使用A类里面的test方法。通过使用super,可以显式的引用被继承接口的默认实现,语法如下:InterfaceName.super.methodName()。

    二、静态方法

    java8中为接口新增了一项功能:定义一个或者更多个静态方法。类似于类中的静态方法,接口定义的静态方法可以独立于任何对象调用。所以,在调用静态方法时,不需要实现接口,也不需要接口的实例,也就是说和调用类的静态方法的方式类似。语法如:接口名字.静态方法名。

    Java 接口静态方法与默认方法类似,只是我们不能在实现类中重写它们

    Animal.java

    1 public interface Animal {
    2     default void fly() {
    3         System.out.println("birds can fly...");
    4     }
    5 
    6     default void swim() {
    7         System.out.println("fishes can swim......");
    8     }
    9 }

    Bird.java

    public class Bird implements Animal {
     }

    Fish.java

    public class Fish implements Animal {
    }

    假如有一个Animal工厂接口,该接口中有一个静态方法create()专门生产不同的Animal,在JDK1.8后由于引入了Lambda表达式,使子类不用覆写该接口的create()方法也可以生产任意的Animal,代码如下:

    1 public interface AnimalFactory {
    2  
    3      static Animal create(Supplier<Animal> supplier) {
    4          return supplier.get();
    5      }
    6  }

    测试类:

     1 public class TestAnimalFactory {
     2 
     3     public static void main(String[] args) {
     4 
     5         // 生产一只鸟
     6         Animal bird = AnimalFactory.create(Bird::new);
     7         bird.fly();
     8      // 生产一条鱼
     9         Animal fish = AnimalFactory.create(Fishe::new);
    10         fish.swim();
    11     }
    12 }

    运行结果:

    birds can fly...
    fishes can swim......

    接口静态方法的“类优先”原则:

    如果一个接口实现类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略,如改写之前的Bird类:

    1 public class Bird implements Animal {
    2  
    3      public void fly() {
    4          System.out.println("Bird类中的fly方法:birds can fly...");
    5      }
    6  }

    测试类:

    1 public class TestMain {
    2 
    3     public static void main(String[] args) {
    4 
    5         Bird bird = new Bird();
    6         bird.fly();
    7     }
    8 }

    运行结果:

    Bird类中的fly方法:birds can fly...

     

    总结

    1、接口默认方法、静态方法可以有多个。

    2、默认方法通过实例调用,静态方法通过接口名调用。

    3、default默认方法关键字只能用在接口中。

    4、默认方法可以被继承,如果继承了多个接口,多个接口都定义了多个同样的默认方法,实现类需要重写默认方法不然会报错。

    5、静态方法不能被继承及覆盖,所以只被具体所在的接口调用。

    参考:https://www.cnblogs.com/wuhenzhidu/p/10753328.html




  • 相关阅读:
    Yiic和migrate
    jquery如何生成图片验证码
    怎么给登录功能设一个访问拦截器
    Maven手动导本地jar到项目
    vue.js页面刷新出现闪烁问题的解决
    Good Routine Names
    someone always forget why we are here!
    第7组(69)团队展示(组长)
    在win7上用Vs2010生成程序无法立即删除的解决办法
    有关objc中的单例
  • 原文地址:https://www.cnblogs.com/qiaoxin11/p/12549006.html
Copyright © 2020-2023  润新知