美文网首页
Java8 函数式编程

Java8 函数式编程

作者: Tim_Hu | 来源:发表于2020-07-28 11:59 被阅读0次

    From: https://lingcoder.gitee.io/onjava8/#/book/13-Functional-Programming

    函数式编程语言操纵代码片段就像操作数据一样容易。 虽然 Java 不是函数式语言,但 Java 8 Lambda 表达式和方法引用 (Method References) 允许你以函数式编程。

    Lambda表达式

    Lambda 表达式是使用最小可能语法编写的函数定义:

    1. Lambda 表达式产生函数,而不是类。 在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是一个类,因此在幕后执行各种操作使 Lambda 看起来像函数 —— 但作为程序员,你可以高兴地假装它们“只是函数”。

    2. Lambda 语法尽可能少,这正是为了使 Lambda 易于编写和使用。

    方法引用

    Java 8 方法引用没有历史包袱。方法引用组成:类名或对象名,后面跟 :: [^4],然后跟方法名称。

    // functional/MethodReferences.java
    
    import java.util.*;
    
    interface Callable { // [1]
      void call(String s);
    }
    
    class Describe {
      void show(String msg) { // [2]
        System.out.println(msg);
      }
    }
    
    public class MethodReferences {
      static void hello(String name) { // [3]
        System.out.println("Hello, " + name);
      }
      static class Description {
        String about;
        Description(String desc) { about = desc; }
        void help(String msg) { // [4]
          System.out.println(about + " " + msg);
        }
      }
      static class Helper {
        static void assist(String msg) { // [5]
          System.out.println(msg);
        }
      }
      public static void main(String[] args) {
        Describe d = new Describe();
        Callable c = d::show; // [6]
        c.call("call()"); // [7]
    
        c = MethodReferences::hello; // [8]
        c.call("Bob");
    
        c = new Description("valuable")::help; // [9]
        c.call("information");
    
        c = Helper::assist; // [10]
        c.call("Help!");
      }
    }
    

    函数式接口

    方法引用和 Lambda 表达式必须被赋值,同时编译器需要识别类型信息以确保类型正确。

    Java 8 引入了 java.util.function 包。它包含一组接口,这些接口是 Lambda 表达式和方法引用的目标类型。 每个接口只包含一个抽象方法,称为函数式方法。

    在编写接口时,可以使用 @FunctionalInterface 注解强制执行此“函数式方法”模式:

    // functional/FunctionalAnnotation.java
    
    @FunctionalInterface
    interface Functional {
      String goodbye(String arg);
    }
    
    interface FunctionalNoAnn {
      String goodbye(String arg);
    }
    
    /*
    @FunctionalInterface
    interface NotFunctional {
      String goodbye(String arg);
      String hello(String arg);
    }
    产生错误信息:
    NotFunctional is not a functional interface
    multiple non-overriding abstract methods
    found in interface NotFunctional
    */
    
    public class FunctionalAnnotation {
      public String goodbye(String arg) {
        return "Goodbye, " + arg;
      }
      public static void main(String[] args) {
        FunctionalAnnotation fa =
          new FunctionalAnnotation();
        Functional f = fa::goodbye;
        FunctionalNoAnn fna = fa::goodbye;
        // Functional fac = fa; // Incompatible
        Functional fl = a -> "Goodbye, " + a;
        FunctionalNoAnn fnal = a -> "Goodbye, " + a;
      }
    }
    

    @FunctionalInterface 注解是可选的; Java 在 main() 中把 Functional 和 FunctionalNoAnn 都当作函数式接口。 在 NotFunctional 的定义中可看到@FunctionalInterface 的作用:接口中如果有多个方法则会产生编译期错误。

    Function源码:

    /*
     * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     *
     * This code is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License version 2 only, as
     * published by the Free Software Foundation.  Oracle designates this
     * particular file as subject to the "Classpath" exception as provided
     * by Oracle in the LICENSE file that accompanied this code.
     *
     * This code is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     * version 2 for more details (a copy is included in the LICENSE file that
     * accompanied this code).
     *
     * You should have received a copy of the GNU General Public License version
     * 2 along with this work; if not, write to the Free Software Foundation,
     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     *
     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     * or visit www.oracle.com if you need additional information or have any
     * questions.
     */
    package java.util.function;
    
    import java.util.Objects;
    
    /**
     * Represents a function that accepts one argument and produces a result.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #apply(Object)}.
     *
     * @param <T> the type of the input to the function
     * @param <R> the type of the result of the function
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Function<T, R> {
    
        /**
         * Applies this function to the given argument.
         *
         * @param t the function argument
         * @return the function result
         */
        R apply(T t);
    
        /**
         * Returns a composed function that first applies the {@code before}
         * function to its input, and then applies this function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of input to the {@code before} function, and to the
         *           composed function
         * @param before the function to apply before this function is applied
         * @return a composed function that first applies the {@code before}
         * function and then applies this function
         * @throws NullPointerException if before is null
         *
         * @see #andThen(Function)
         */
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        /**
         * Returns a composed function that first applies this function to
         * its input, and then applies the {@code after} function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of output of the {@code after} function, and of the
         *           composed function
         * @param after the function to apply after this function is applied
         * @return a composed function that first applies this function and then
         * applies the {@code after} function
         * @throws NullPointerException if after is null
         *
         * @see #compose(Function)
         */
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    
        /**
         * Returns a function that always returns its input argument.
         *
         * @param <T> the type of the input and output objects to the function
         * @return a function that always returns its input argument
         */
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Java8 函数式编程

          本文链接:https://www.haomeiwen.com/subject/ahkfrktx.html