• 【java8】静态方法与默认方法


    静态方法和默认方法都必须有自己的实现,如果一个类既有静态方法,又有默认方法,还有一个抽象方法,那么它还是一个函数式接口。

    静态方法

    Java8为接口引入了静态方法功能。静态方法必须有自己的实现,而不能仅仅是一个接口声明,不然编译是会报错的。

    以前为一个接口编写一个工具类,需另外写一个工具类如XxxUtil,现在可以直接将工具类的方法直接写在接口的静态方法中了。后面我们会看到JDK为我们提供的工具方法大部分都在函数式接口中,如java.util.function.Function。

    package java.util.function;
    
    import java.util.Objects;
    
    @FunctionalInterface
    public interface Function<T, R> {
    
        R apply(T t);
    
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    函数式接口Function提供一个抽象方法(apply),两个默认方法(compose和andThen),一个静态方法(identity)。

    接口中的方法默认都是抽象的和public的。

    默认方法

    问题:java 8之前接口增加一个新的方法,所有的实现类都得实现此方法。

    为了解决这个问题,java8为接口引入了默认方法,如果接口新增了一个默认方法,所有的实现类无需实现此方法(像继承类的方法一样继承了默认方法的具体实现)。

    默认方法的使用

    默认方法由default修饰符修饰,并像类中声明的其他方法一样包含方法体。

    package com.morris.java8.defaultmethod;
    
    public class DefaultMethodExample {
    
        public static void main(String[] args) {
    
            A a = () -> 10;
    
            System.out.println(a.isEmpty());
        }
    
        @FunctionalInterface
        interface A {
    
            int size();
    
            default boolean isEmpty() {
                return 0 == size();
            }
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    解决多继承冲突的三条原则

    如果一个类使用相同的函数签名从多个地方(比如另一个类或接口)继承了方法,通过三条规则可以进行判断。

    • 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。

    • 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。

    • 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,显式地选择使用哪一个默认方法的实现。

    类的方法优先级最高:

    package com.morris.java8.defaultmethod;
    
    public class MultiExtendExample {
    
        public static void main(String[] args) {
            new C().hello(); // Hello from C
        }
    
        public interface A {
            default void hello() {
                System.out.println("Hello from A");
            }
        }
        public interface B extends A {
            @Override
            default void hello() {
                System.out.println("Hello from B");
            }
        }
        public static class C implements B, A {
            @Override
            public void hello() {
                System.out.println("Hello from C");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    最具体的实现优先:

    package com.morris.java8.defaultmethod;
    
    public class MultiExtendExample1 {
    
        public static void main(String[] args) {
            new C().hello(); // Hello from B
        }
    
        public interface A {
            default void hello() {
                System.out.println("Hello from A");
            }
        }
        public interface B extends A {
            @Override
            default void hello() {
                System.out.println("Hello from B");
            }
        }
        public static class C implements B, A {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    冲突依旧无法解决,只能在类中覆盖该默认方法:

    package com.morris.java8.defaultmethod;
    
    public class MultiExtendExample2 {
    
        public static void main(String[] args) {
            new D().hello(); // Hello from D
        }
    
        public interface A {
            void hello();
        }
        public interface B extends A {
            @Override
            default void hello() {
                System.out.println("Hello from B");
            }
        }
        public interface C extends A {
            @Override
            default void hello() {
                System.out.println("Hello from C");
            }
        }
        public static class D implements B, C {
            @Override
            public void hello() {
                System.out.println("Hello from D");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 相关阅读:
    使用.NET开发VSTO工具快速将PPT导出为图片
    第十四章《多线程》第2节:线程的生命周期
    技术分享 | 接口自动化测试如何处理 Header cookie
    面试题-React(十四):什么是高阶组件(HOC)及其作用
    Go语言中实现应用IP防火墙
    JavaScript(六):事件捕获与冒泡
    深眸科技迭代深度学习算法,以AI机器视觉技术扩围工业应用场景
    Android Jetpack组件架构 :LiveData的使用和原理
    神经网络预测指标是什么,神经网络怎么预测数据
    STM32CubeMX教程29 USB_HOST - 使用FatFs文件系统读写U盘
  • 原文地址:https://blog.csdn.net/u022812849/article/details/125480215