Java 8 发布至今已经超过 10 年,其引入的 Lambda 表达式和 Stream API 早已被广泛讨论。但一个有趣的现实是:在企业级项目中,能够熟练且恰当地运用函数式编程来优化代码逻辑的开发者,似乎仍是少数派。
在日常的代码评审中,你是否也常被层叠嵌套的 if-else 语句困扰?这些条件分支让核心业务逻辑显得臃肿且不易读。我们能否借助函数式的思想,将这些“分支”巧妙地收敛起来呢?
基于这个想法,我尝试封装了几个简单的工具方法,并在团队中进行了实践,效果还不错。虽然封装本身看起来并不复杂,甚至有些“丑陋”,但它们确实能帮助我们在业务层减少大量的条件判断代码,让逻辑更清晰。下面就来分享一下这几个小工具。

isBlankAccept
这是第一个案例,源自于一种常见的模式:当某个字符串不为空时,才执行一段特定的业务逻辑。看下面这段典型的代码:
public void test(User user){
// ...
if(isBlank(user.getName())){
// doSomething
wrapper.innerJoin(Order.class, on -> on.eq(Order::getUserId, User::getId)
.eq(Order::getState, 10));
wrapper.and(p -> p.like(Order::getAddress, n)
.or().like(Order::getCode, n)
.or().like(User::getName, n));
// doSomething
}
// ...
}
这类场景非常普遍,比如参数校验后的处理、动态 SQL 拼接、或是根据条件生成特定内容等。其本质都是 “当条件 P 成立时,执行动作 A”。
我们可以将这个模式抽象成一个函数式工具,将 if 判断隐藏在工具内部,让业务代码更专注于“要做什么”:
FunUtil.isBlankAccept(user.getName, n -> {
// doSomething
wrapper.innerJoin(Order.class, on -> on.eq(Order::getUserId, User::getId)
.eq(Order::getState, 10));
wrapper.and(p -> p.like(Order::getAddress, n)
.or().like(Order::getCode, n)
.or().like(User::getN
ame, n));
// doSomething
});
这样一来,业务方法中就少了一层缩进和一个 if 语句。实现这个工具方法非常简单:
public static void isBlankAccept(final CharSequence cs, Consumer<CharSequence> action){
if (isBlank(cs)) {
action.accept(cs);
}
}
这里的 isBlank 方法可以直接使用 Apache Commons Lang、Spring Framework 或 Hutool 等工具库中的实现,当然也可以自己编写。对应的 isNotBlankAccept 方法逻辑正好相反,按需实现即可。
isTrueRun
上面的 isBlankAccept 是针对字符串空值判断的特化方法。那么,对于更通用的布尔条件判断呢?这就是我们的第二个工具:isTrueRun 和 isFalseRun。
其核心思想是:如果条件为真,则执行一段代码逻辑。对于不需要参数的操作,可以使用 Runnable:
public static void isTrueRun(final boolean flag, Runnable action){
if (flag) {
action.run();
}
}
如果需要传入参数给要执行的逻辑,则可以使用泛型结合 Consumer<T>:
public static <T> void isTrueRun(boolean flag, T t, Consumer<T> action){
if (flag) {
action.accept(t);
}
}
// 使用示例
String name = “业余草”;
isTrueRun(FunUtil.isNotBlank(name), name, t -> {
System.out.println(“Processing: “ + t);
// 业务逻辑
});
当逻辑需要两个参数时,可以进一步扩展到 BiConsumer<T, U>:
public static <T, U> void isTrueRun(boolean flag, T t, U u, BiConsumer<T, U> action){
if (flag) {
action.accept(t, u);
}
}
// 使用示例
isTrueRun(true, name, wrapper, (t, w) -> {
w.like(…, t);
});
isTrueRunGet
前两个案例的工具方法都没有返回值。但在实际开发中,我们经常需要根据条件计算并返回一个值。这就是第三个工具 isTrueRunGet 要解决的问题。
对于无参数但需要返回值的场景,可以使用 Supplier<T>:
public static <T> T isTrueRunGet(final boolean flag, Supplier<T> action){
if (flag) {
// 执行并返回结果
return action.get();
}
// 或抛异常,或返回默认值
return null;
}
// 使用示例
String result = isTrueRunGet(
FunUtil.isNotBlank(name),
() -> “Processed: “ + name.toUpperCase()
);
为了让方法更健壮,避免返回 null 导致潜在的 NullPointerException,我们可以增加一个默认值参数:
public static <T> T isTrueRunGet(final boolean flag, Supplier<T> action, T defaultValue){
if (flag) {
return action.get();
}
return defaultValue;
}
// 使用示例
String result = isTrueRunGet(
FunUtil.isNotBlank(name),
() -> processName(name),
“默认是业余草”
);
如果需要根据输入参数计算返回值,则可以使用 Function<T, R>:
public static <T, R> R isTrueRunGet(final boolean flag, T input, Function<T, R> action, R defaultValue){
if (flag) {
return action.apply(input);
}
return defaultValue;
}
// 使用示例
String result = isTrueRunGet(
FunUtil.isNotBlank(name),
name,
t -> t.trim().toUpperCase(),
“#业余草”
);
更进一步,为了更安全地处理可能为空的结果,我们可以让工具方法直接返回 Optional<T>,这是 Java 8 中处理空值的最佳实践之一:
public static <T> Optional<T> isTrueRunGet(final boolean flag, Supplier<T> action){
if (flag) {
return Optional.ofNullable(action.get());
}
return Optional.empty();
}
// 使用
Optional<String> result = isTrueRunGet(
FunUtil.isNotBlank(name),
() -> processName(name)
);
result.ifPresent(System.out::println);
看到这里,可能有读者会指出:“你这些工具方法内部不还是用了 if 吗?” 没错,我们封装的目的并不是从地球上彻底消灭 if 关键字,而是将条件判断的细节与业务动作的执行进行解耦,提升业务代码的声明性和可读性。

如果你追求的是极致的“无 if”风格,也可以使用三元表达式改造返回值版本的方法:
public static <T> T isTrueRunGet(boolean flag, Supplier<T> action, T defaultValue){
return flag ? action.get() : defaultValue;
}
广泛而恰当地使用这类函数式工具后,你的代码会变得更紧凑、更富表达力,当然,也可能让不熟悉这种范式的人觉得更像“诗”(或者别的什么)。
总结
归根结底,代码是写给人看的,其次才是让机器执行。本文分享这几个小工具,与其说是为了消灭 if-else,不如说是一次对函数式编程思维的轻度实践推广。
在实际开发中,我发现即便是 AI 生成的代码,也较少主动使用这类模式,除非在指令中明确要求。这或许说明,函数式编程不仅仅是一些语法糖,更是一种需要刻意练习和理解的思维方式。
掌握 Lambda 表达式、Stream API 只是起点,如何像本文这样,将其思想融入日常工具封装与业务抽象,才是更进阶的课题。本文的示例仅是抛砖引玉,更多实用的函数式编程技巧和设计模式,可以在云栈社区的Java板块与大家深入探讨。
