《On Java 8》笔记-第十三章 函数式编程**

总结

用一个接口对象去应用绑定一个类的方法(接口方法和类方法有相同的辨识符)
用 接口.方法(参数…)的方法调用,或者获取返回值

  • RecursiveFibonacci.java
public class RecursiveFibonacci {
  IntCall fib;

  RecursiveFibonacci() {
    fib = n -> n == 0 ? 0 :
               n == 1 ? 1 :
               fib.call(n - 1) + fib.call(n - 2);
  }

  int fibonacci(int n) { return fib.call(n); }

  public static void main(String[] args) {
    RecursiveFibonacci rf = new RecursiveFibonacci();
    for(int i = 0; i <= 10; i++)
      System.out.println(rf.fibonacci(i));
  }
}
>输出结果:
0
1
1
2
3
5
8
13
21
34
55
  • UnboundMethodReference.java
class X {
  String f() { return "X::f()"; }
}

interface MakeString {
  String make();
}

interface TransformX {
  String transform(X x);
}

public class UnboundMethodReference {
  public static void main(String[] args) {
    // MakeString ms = X::f; // [1]
    TransformX sp = X::f;
    X x = new X();
    System.out.println(sp.transform(x)); // [2]
    System.out.println(x.f()); // 同等效果
  }
}
>输出结果:
X::f()
X::f()
  • [1],我们尝试把 X 的 f() 方法引用赋值给 MakeString。结果:即使 make() 与 f() 具有相同的签名,编译也会报“invalid method reference”(无效方法引用)错误。 这是因为实际上还有另一个隐藏的参数:我们的老朋友 this。 你不能在没有 X 对象的前提下调用 f()。 因此,X :: f 表示未绑定的方法引用,因为它尚未“绑定”到对象。
    要解决这个问题,我们需要一个 X 对象,所以我们的接口实际上需要一个额外的参数的接口,如上例中的 TransformX。 如果将 X :: f 赋值给 TransformX,这在 Java 中是允许的。这次我们需要调整下心里预期——使用未绑定的引用时,函数方法的签名(接口中的单个方法)不再与方法引用的签名完全匹配。 理由是:你需要一个对象来调用方法。
  • [2] 的结果有点像脑筋急转弯。 我接受未绑定的引用并对其调用 transform(),将其传递给 X,并以某种方式导致对 x.f() 的调用。 Java 知道它必须采用第一个参数,这实际上就是 this,并在其上调用方法。
  • 在编写接口时,可以使用 @FunctionalInterface 注解强制执行此“函数式方法”模式。
  • TriFunctionTest.java
@FunctionalInterface
interface TriFunction<T, U, V, R> {
    R apply(T t, U u, V v);
}

public class TriFunctionTest {
  static int f(int i, long l, double d) { 
  	return 99; 
  }
  public static void main(String[] args) {
    TriFunction<Integer, Long, Double, Integer> tf =
      TriFunctionTest::f;
      System.out.println(tf.apply(1, 1L, 1.0));
    // tf = (i, l, d) -> i+l+d;		//error
      tf = (i, l, d) -> i;
    System.out.println(tf.apply(13, 14L, 15.0));
  }
}
>输出结果:
99
13
  • TransformFunction.java
import java.util.function.*;

class I {
  public I() {
    System.out.println("Create I");
  }

  @Override
  public String toString() { return "I"; }
}

class O {
  public O() {
    System.out.println("Create O");  
  }

  @Override
  public String toString() { return "O"; }
}

public class TransformFunction {
  static Function<I,O> transform(Function<I,O> in) {
    System.out.println("2");
    return in.andThen(o -> {
      System.out.println("Accept a O");
      System.out.println(o);
      return o;
    });
  }
  public static void main(String[] args) {
    System.out.println("1");
    Function<I,O> f2 = transform(i -> {
      System.out.println("Accept a I");
      System.out.println(i);
      return new O();
    });
    System.out.println("3");
    O o = f2.apply(new I());
  }
}
>输出结果:
1
2
3
Create I
Accept a I
I
Create O
Accept a O
O

- 闭包

  • 实际上只要有内部类,就会有闭包(Java 8 只是简化了闭包操作)。在 Java 8 之前,变量 x 和 i 必须被明确声明为 final。在 Java 8 中,内部类的规则放宽,包括等同 final 效果。
  • Curry3Args.java
import java.util.function.*;

public class Curry3Args {
   public static void main(String[] args) {
      Function<String,
        Function<String,
          Function<String, String>>> sum =
            a -> b -> c -> a + b + c;
      Function<String,
        Function<String, String>> hi =
          sum.apply("Hi ");
      Function<String, String> ho =
        hi.apply("Ho ");
      System.out.println(ho.apply("Hup"));
   }
}
>输出结果:
Hi Ho Hup
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值