zoukankan      html  css  js  c++  java
  • Java8 新特性----函数式接口,以及和Lambda表达式的关系

       这里来讲解一下Java8 新特性中的函数式接口, 以及和Lambda 表达式的关系。看到过很多不少介绍Java8特性的文章,都会介绍到函数式接口和lambda表达式,但是都是分别介绍,没有将两者的关系说明清楚,在这里,把自己的理解整理如下:

    一、函数式接口:

      函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口(Single Abstract Method)。定义了这种类型的接口,使得以其为参数的方法,可以在调用时,使用一个lambda表达式作为参数。从另一个方面说,一旦我们调用某方法,可以传入lambda表达式作为参数,则这个方法的参数类型,必定是一个函数式的接口,这个类型必定会使用@FunctionalInterface进行修饰。

      从SAM原则上讲,这个接口中,只能有一个函数需要被实现,但是也可以有如下例外:

        1. 默认方法与静态方法并不影响函数式接口的契约,可以任意使用,即

          函数式接口中可以有静态方法,一个或者多个静态方法不会影响SAM接口成为函数式接口,并且静态方法可以提供方法实现

          可以由 default 修饰的默认方法方法,这个关键字是Java8中新增的,为的目的就是使得某一些接口,原则上只有一个方法被实现,但是由于历史原因,不得不加入一些方法来兼容整个JDK中的API,所以就需要使用default关键字来定义这样的方法

        2. 可以有 Object 中覆盖的方法,也就是 equals,toString,hashcode等方法。

      JDK中以前所有的函数式接口都已经使用 @FunctionalInterface 定义,可以通过查看JDK源码来确认,以下附JDK 8之前已有的函数式接口:

                java.lang.Runnable

                java.util.concurrent.Callable

                java.security.PrivilegedAction

                java.util.Comparator

                java.io.FileFilter

                java.nio.file.PathMatcher 

                java.lang.reflect.InvocationHandler

                java.beans.PropertyChangeListener

                java.awt.event.ActionListener  

                javax.swing.event.ChangeListener

    如:

    @FunctionalInterface
    public interface Runnable {
        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }

    以下为一个自定义函数式接口的示例:

    定义:

    @FunctionalInterface
    interface Converter<F, T> {
    
        T convert(F from);
    
    }

    使用:

    Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
    
    Integer converted = converter.convert("123");

    注:方法和构造函数引用在Java8中可以通过 :: 操作符调用

      自行设计的方法中, 如果可以接收 lambda 表达式, 则可以使用 Function 作为参数, 如下为一些已经实现的函数式接口:

         // Function<T, R> -T作为输入,返回的R作为输出
    
        Function<String,String> function = (x) -> {System.out.print(x+": ");return "Function";};
    
        System.out.println(function.apply("hello world"));
    
      
    
        //Predicate<T> -T作为输入,返回的boolean值作为输出
    
        Predicate<String> pre = (x) ->{System.out.print(x);return false;};
    
        System.out.println(": "+pre.test("hello World"));
    
     
    
        //Consumer<T> - T作为输入,执行某种动作但没有返回值
    
        Consumer<String> con = (x) -> {System.out.println(x);};
    
        con.accept("hello world");
    
     
    
        //Supplier<T> - 没有任何输入,返回T
    
        Supplier<String> supp = () -> {return "Supplier";};
    
        System.out.println(supp.get());
    
     
    
        //BinaryOperator<T> -两个T作为输入,返回一个T作为输出,对于“reduce”操作很有用
    
        BinaryOperator<String> bina = (x,y) ->{System.out.print(x+" "+y);return "BinaryOperator";};
    
        System.out.println("  "+bina.apply("hello ","world"));

    二、Lambda表达式(这里只是简单提一下)

    书写方法:  e -> System.out.println( e )

        1. 三部分构成

            参数列表

            符号 ->

            函数体 : 有多个语句,可以用{} 包括, 如果需要返回值且只有一个语句,可以省略 return

        2. 访问控制:

            可以访问类的成员变量和局部变量(非final会自动隐含转为final)

      以上主要是对于函数式接口的一些简单介绍,如有疏漏,欢迎指正

  • 相关阅读:
    宿主机无法访问CentOS7上Jenkins服务的解决办法
    415. Add Strings
    367. Valid Perfect Square
    326. Power of Three
    258. Add Digits
    231. Power of Two
    204. Count Primes
    202. Happy Number
    172. Factorial Trailing Zeroes
    171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/ownraul/p/5551545.html
Copyright © 2011-2022 走看看