话不多说,看看箭头方法->实现的策略模式加减乘除。
第一个策略接口
@FunctionalInterface
public interface Operation {
double apply(double a, double b);
}
具体实现
public class Calculator {
// 加法策略
public static final Operation ADD = (a, b) -> a + b;
// 减法策略
public static final Operation SUBTRACT = (a, b) -> a - b;
// 乘法策略
public static final Operation MULTIPLY = (a, b) -> a * b;
// 除法策略
public static final Operation DIVIDE = (a, b) -> {
if (b == 0) {
throw new ArithmeticException("Cannot divide by zero");
}
return a / b;
};
}
- 当只用一个参数,可以不需要括号
()
。 然而,这是一个特例。 - 正常情况使用括号
()
包裹参数。 为了保持一致性,也可以使用括号()
包裹单个参数,虽然这种情况并不常见。 - 如果没有参数,则必须使用括号
()
表示空参数列表。 - 对于多个参数,将参数列表放在括号
()
中。
使用策略模式
public class Context {
private Operation operation;
public void setOperation(Operation operation) {
this.operation = operation;
}
public double executeOperation(double a, double b) {
return operation.apply(a, b);
}
}
测试
public class Main {
public static void main(String[] args) {
Context context = new Context();
// 测试加法
context.setOperation(Calculator.ADD);
System.out.println("10 + 5 = " + context.executeOperation(10, 5));
// 测试减法
context.setOperation(Calculator.SUBTRACT);
System.out.println("10 - 5 = " + context.executeOperation(10, 5));
// 测试乘法
context.setOperation(Calculator.MULTIPLY);
System.out.println("10 * 5 = " + context.executeOperation(10, 5));
// 测试除法
context.setOperation(Calculator.DIVIDE);
System.out.println("10 / 5 = " + context.executeOperation(10, 5));
// 测试除以零
try {
System.out.println("10 / 0 = " + context.executeOperation(10, 0));
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
递归:整数 n 的阶乘
// functional/IntCall.java
interface IntCall {
int call(int arg);
}
// functional/RecursiveFactorial.java
public class RecursiveFactorial {
static IntCall fact;
public static void main(String[] args) {
fact = n -> n == 0 ? 1 : n * fact.call(n - 1);
for(int i = 0; i <= 10; i++)
System.out.println(fact.call(i));
}
}
Fibonacci
序列
// functional/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));
}
}
方法引用。类名或对象名,后面跟::,然后跟方法名称。
// functional/MethodReferences.java
import java.util.*;
interface Callable { // [1]从单一方法接口开始
void call(String s);
}
class Describe {
void show(String msg) { // [2](参数类型和返回类型)符合 **Callable** 的 `call()` 的签名。
System.out.println(msg);
}
}
public class MethodReferences {
static void hello(String name) { // [3]也符合 `call()` 的签名。
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();
//我们将 **Describe** 对象的方法引用赋值给 **Callable** ,它没有 `show()` 方法,而是 //`call()` 方法。 但是,Java 似乎接受用这个看似奇怪的赋值,因为方法引用符合 **Callable** 的 //`call()` 方法的签名。
Callable c = d::show;
c.call("call()"); //我们现在可以通过调用 `call()` 来调用 `show()`,因为 Java 将 `call()` 映射到 `show()`。
c = MethodReferences::hello; // 这是一个**静态**方法引用。
c.call("Bob");
c = new Description("valuable")::help; // 对已实例化对象的方法的引用,有时称为*绑定方法引用*。
c.call("information");
c = Helper::assist; // [10]获取静态内部类的方法引用的操作
c.call("Help!");
}
}
Runnable run接口无参数,无返回值
// functional/RunnableMethodReference.java
// 方法引用与 Runnable 接口的结合使用
class Go {
static void go() {
System.out.println("Go::go()");
}
}
public class RunnableMethodReference {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
System.out.println("Anonymous");
}
}).start();
new Thread(
() -> System.out.println("lambda")
).start();
new Thread(Go::go).start();
}
}
未绑定的方法引用
未绑定的方法引用是指没有关联对象的普通(非静态)方法。使用未绑定的引用之前,我们必须先提供对象。
// functional/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; //该方法不是静态方法,只是普通的成员方法,并且还没有绑定对象,所以错误
TransformX sp = X::f;//声明传入的参数调用了X类型的f方法代码。
X x = new X(); //参数
System.out.println(sp.transform(x)); // sp调用方法
System.out.println(x.f()); // 同等效果
}
}
未绑定的方法与多参数的结合运用
class This {
void two(int i, double d) {}
void three(int i, double d, String s) {}
void four(int i, double d, String s, char c) {}
}
interface TwoArgs {
void call2(This athis, int i, double d);
}
interface ThreeArgs {
void call3(This athis, int i, double d, String s);
}
interface FourArgs {
void call4(
This athis, int i, double d, String s, char c);
}
public class MultiUnbound {
public static void main(String[] args) {
TwoArgs twoargs = This::two;
ThreeArgs threeargs = This::three;
FourArgs fourargs = This::four;
This athis = new This();
twoargs.call2(athis, 11, 3.14);
threeargs.call3(athis, 11, 3.14, "Three");
fourargs.call4(athis, 11, 3.14, "Four", 'Z');
}
}
构造函数的引用
class Dog {
String name;
int age = -1; // For "unknown"
Dog() { name = "stray"; }
Dog(String nm) { name = nm; }
Dog(String nm, int yrs) { name = nm; age = yrs; }
}
interface MakeNoArgs {
Dog make();
}
interface Make1Arg {
Dog make(String nm);
}
interface Make2Args {
Dog make(String nm, int age);
}
public class CtorReference {
public static void main(String[] args) {
MakeNoArgs mna = Dog::new; // [1]
Make1Arg m1a = Dog::new; // [2]
Make2Args m2a = Dog::new; // [3]
Dog dn = mna.make();
Dog d1 = m1a.make("Comet");
Dog d2 = m2a.make("Ralph", 4);
}
}
Dog 有三个构造函数,函数接口内的 make()
方法反映了构造函数参数列表( make()
方法名称可以不同)