zoukankan      html  css  js  c++  java
  • Java8 --- 函数式接口@FunctionalInterface及default关键字

    1. 关于Comparator和Comparable

    既然提到了Comparator,那就大致来说一下Comparator和Comparable接口的区别。

    Comparator是一种策略模式,即被比较的对象自身不需要做任何改变(实现任何排序接口),而是通过实例化一个Comparator策略来实现对象之间的排序。

    Comparable支持对象自身进行改变(对象自身实现Comparable接口),从而具有排序功能。

    举个例子来说,一组对象需要用Collection的sort方法进行排序,有两种方法,要么是对象实现Comparable接口,自身具有可排序属性;要么是实现一个Comparator比较器,在调用sort方法时传入。

    下面再来说一说Lambda表达式。

    2. Lambda表达式

    我们都知道,Lambda表达式是Java里面的函数式编程,那么在使用Lambda表达式首先要满足这样一个条件:首先他的类型是interface,而且有且仅有一个抽象方法。那么下面我们先来看一个使用Lambda表达式的例子。

    先看一下Java7中的表达:

    public class LambdaTest {
    
        public static void main(String[] args) {
    
            Say test1 = new Say() {
    
                @Override
    
                public void saySomthing(String something) {
    
                    System.out.println(something);
    
                }
    
            };
    
            test2.saySomthing("hello");
    
    }
    
    interface Say {
    
        void saySomthing(String something);
    
    }

    使用Lambda表达式后的Java8中的表达:

    public class LambdaTest {
    
        public static void main(String[] args) {
    
            Say test2 = System.out::println;
    
            test2.saySomthing("hello");
    
        }
    
    }
    
    interface Say {
    
        void saySomthing(String something);
    
    }

    那么类似的,我们要实现一个Comparator比较器会这样写:

    public class LambdaTest {
    
        public static void main(String[] args) {
    
           Comparator<Book> bookComparator = Comparator.comparing(Book::getPrice);
    
           
    
           Book book1 = new Book("a", 1);
    
           Book book2 = new Book("b", 1);
    
           System.out.println(bookComparator.compare(book1, book2));
    
        }
    
    }
    
    class Book {
    
        private String name;
    
        private Integer price;
    
        
    
        // 省略constructor/getter/setter
    
    }

    这样写完全OK,可是我们去看一下Comparator接口的源码,可能会觉得略微有点诧异。

    可以注意到Comparator接口的源码有这样几个点:

    @FunctionalInterface注解的作用

    Comparator接口里有多个方法(两个抽象方法和多个default方法)

    default关键字的含义

    下面逐一来解释一下上面这三个点。

    (1) @FunctionalInterface注解的作用

    @FunctionalInterface标注在一个接口上,说明这个接口是一个函数式接口。

    ​那么关于函数式接口,有如下特点:

    ​有且只有一个抽象方法

    可以有多个静态方法

    可以有多个default方法(默认方法)

    可以有多个Object的public的抽象方法

    (2) Comparator接口里有多个方法(两个抽象方法和多个default方法)

    可以看到​Comparator接口里除了有compare这个抽象方法,还有一个equals抽象方法,但是如上所说,函数式接口里允许有Object的public的抽象方法。

    (3) ​default关键字的含义

    default关键字修饰的接口方法可以有默认的方法体。当接口的实现类实现接口的时候,可以不去实现default关键字修饰的方法。

    这样做是为了解决这样一种场景:

    假设有一个接口定义如下:

    interface TestInterFace {
    
        void doSomething();
    
    }

    在一个应用中有该接口的大量实现类,可是突然这个接口里面需要新加一个方法doAnother()。此时,我们要在应用所有实现了这个接口的类中加上doAnother()的实现,这样会导致两个问题:一是修改的幅度对比较大;二是不是所有的实现类都需要去实现doAnother()方法。

    default关键字就是为了解决这样的问题。在doAnother()方法前加上default关键字,之前的接口实现类不去实现doAnother()方法也不会报错。如果新的实现类实现这个方法,就等于该实现类覆盖了这个方法,这样最终的运行结果也是符合Java的多态性的。

    但是需要注意的是,default关键字也不建议随便使用。

    假设有两个接口:InterfaceA和InterfaceB​,他们都有一个default void test()方法,现在又Class C同时实现InterfaceA和InterfaceB,在调用test()方法时就会出错,因为这样会引起二义性,编译器无法知道C调用的究竟是那一个test()方法。

    ————————————————

    版权声明:本文为CSDN博主「dela_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/dela_/article/details/8379477

  • 相关阅读:
    [ICPC2016上海F] Mr. Panda and Fantastic Beasts
    [ICPC2016上海E] Bet
    [ICPC2016上海D] Ice Cream Tower
    [ICPC2016上海L] World Cup
    [CCPC2020长春F] Strange Memory
    [CF1495C] Garden of the Sun
    【实战】牛年的第一个SQL注入漏洞
    【实战】一次有趣的HPP绕WAF记录
    [模板]二分答案
    字典树及其应用
  • 原文地址:https://www.cnblogs.com/lc0605/p/11771278.html
Copyright © 2011-2022 走看看