


























知道不等于会用,会用才是真本事
在我们的项目中,有一个 EnterpriseContext 工具类,用于管理当前登录企业的 Session 信息。代码很简单:
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class EnterpriseContext {
public static final String ENTERPRISE_SESSION = "enterprise_info";
private static HttpSession getSession() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getSession();
}
public static void setEnterpriseVo(EnterpriseVO loginEnterprise) {
getSession().setAttribute(ENTERPRISE_SESSION, loginEnterprise);
}
public static EnterpriseVO getEnterpriseVo() {
return (EnterpriseVO) getSession().getAttribute(ENTERPRISE_SESSION);
}
}
这段代码在非 Web 请求上下文中调用时会抛出 NullPointerException。比如:
因为 RequestContextHolder.getRequestAttributes() 在没有绑定请求的情况下会返回 null,后续的 .getRequest() 就直接 NPE 了。
我把问题反馈给开发者,他很快就给出了修复版本:
private static HttpSession getSession() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) {
return null;
}
HttpServletRequest request = attributes.getRequest();
return request.getSession();
}
public static void setEnterpriseVo(EnterpriseVO loginEnterprise) {
HttpSession session = getSession();
if (session != null) {
session.setAttribute(ENTERPRISE_SESSION, loginEnterprise);
}
}
public static EnterpriseVO getEnterpriseVo() {
HttpSession session = getSession();
if (session != null) {
return (EnterpriseVO) session.getAttribute(ENTERPRISE_SESSION);
}
return null;
}
NPE 确实被修复了。代码逻辑正确,也能正常跑。不过,我跟开发者说,代码不够优雅。
开发者思考片刻,跟另一个小伙面面相觑,反来追问我:
"那你的优雅方案是什么?"
我一笑置之,没有直接答复。
如果我提示使用"Optional",以他的技术能力,一定立刻就能写出优雅的版本。但我不说,他却想不到。
问题出在哪?
他知道 基于Optional进行优雅判空的知识。但在这个场景下,他的思维被"if 判空"这个惯用模式束缚住了,没有主动想到把 Optional 用起来。
知识就在那里,他却没用上。
private static Optional<HttpSession> getSession() {
return Optional.ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.map(ServletRequestAttributes::getRequest)
.map(HttpServletRequest::getSession);
}
public static void setEnterpriseVo(EnterpriseVO loginEnterprise) {
getSession().ifPresent(session -> session.setAttribute(ENTERPRISE_SESSION, loginEnterprise));
}
public static EnterpriseVO getEnterpriseVo() {
return (EnterpriseVO) getSession()
.map(session -> session.getAttribute(ENTERPRISE_SESSION))
.orElse(null);
}
// 三步走:先取值,再判断,最后使用
ServletRequestAttributes attributes = ...;
if (attributes == null) {
return null;
}
HttpServletRequest request = attributes.getRequest();
return request.getSession();
attributesreturn// 一行链式调用,意图一目了然
return Optional.ofNullable(...)
.map(ServletRequestAttributes::getRequest)
.map(HttpServletRequest::getSession);
| 维度 | if 版本 | Optional 版本 |
|---|---|---|
| 代码行数 | 更多 | 更少 |
| 临时变量 | 需要多个 | 无需 |
| 空值语义 | 隐式(靠 return null) | 显式(Optional 类型) |
| 嵌套层级 | 多层 if 可能嵌套 | 链式调用保持扁平 |
| 编译期安全 | 容易漏判 | 强制处理空值 |
| 可读性 | 常规 | 更声明式 |
这个小故事反映了一个普遍现象:
知识的掌握 ≠ 知识的运用
很多开发者都能准确说出 Optional 是用来"避免空指针异常"的。但到了实际编码时,第一反应仍然是 if (obj != null)。
这种现象太常见了:
知道是知识,用出来才是技能。
知识的价值不在于你拥有多少,而在于你在恰当的时机能否想起并使用它。
面试中能流畅背诵"Optional 的四大方法"、"Stream 的中间操作与终止操作",这当然算知识。但如果写出来的代码依然是下面这样的,那这个知识就没有真正转化为能力,只能算是“八股文”式的低效学习。
List<String> result = new ArrayList<>();
for (String s : list) {
if (s != null && s.startsWith("A")) {
result.add(s);
}
}
知识只是原材料,思考才是加工厂。不经过主动思考的知识,就像一本从未翻阅的字典——它就在书架上,但你遇到生字时却想不起来去查。
回到最初的那个问题。开发者问我的"优雅方案"到底是什么?
其实不是 Optional,而是在合适的场景下主动想起并运用 Optional 的思维习惯。
技术工具永远在变,但"学以致用"的能力是贯穿始终的。
知道很多道理,却依然写不好代码——原因往往不是知识不够,而是思考不够。
知识就是力量,但运用知识的能力,才是真正的力量。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。