java中必须通过getter/setter访问私有属性,因直接访问会破坏封装、引发空指针异常、导致数据不一致和安全风险;python和ts虽无语法强制,但绕过getter/setter同样跳过校验与副作用控制。

直接访问对象属性看似简单,但容易引发封装破坏、空指针异常、数据不一致和安全风险等问题。
违背封装原则,暴露内部实现
面向对象的核心是封装——把数据和操作数据的方法绑定,并隐藏内部细节。
- Java 中私有属性(
private)必须通过 getter/setter 访问,直接写obj.name会编译失败; - Python 中虽无语法强制,但用双下划线(
__attr)或约定前缀(如_attr)表示受保护,直接访问等于绕过校验逻辑; - TypeScript/JavaScript 虽无访问控制,但类设计意图仍应通过方法暴露行为,而非裸露字段。
运行时易崩溃:未判空导致报错
JavaScript 中 obj.user.name 在 obj.user 为 null 或 undefined 时抛出 Cannot read property 'name' of undefined;
Java 中 obj.getProfile().getAddress().getCity() 链式调用若中间任一环节为空,直接触发 NullPointerException;
这类错误本可通过可选链(?.)、空值合并(??)或防御性判空规避,但直接访问让问题潜伏在运行时。
属性访问可能隐含副作用或计算开销
- 若属性是
@property(Python)、get访问器(JS/TS)或 getter 方法(Java),每次点号访问都执行函数逻辑,重复调用浪费资源; - 示例:循环中反复写
item.createdAt.toLocaleString(),不如提前提取const timeStr = item.createdAt.toLocaleString(); - 即使用了
__slots__或无__dict__的 Python 类,只要属性背后是描述符或计算逻辑,点号开销就不可忽略。
权限与校验逻辑被跳过
银行账户类的 __balance 是私有字段,但若某个内部方法直接写 self.__balance -= 10000 而不走 withdraw(amount) 校验,就可能突破余额限制、绕过日志审计或风控规则;
Web 后端若允许前端传入对象路径字符串并直接反射取值(如 user.${field}),还可能引发不安全的直接对象引用(IDOR)漏洞。
- 封装不是“防君子”,而是明确契约边界
- 空值不是意外,是常态,需主动应对
- 属性读取不是零成本操作,尤其在高频循环或深层嵌套中
- 安全与一致性依赖访问路径的统一管控,而非放任直连











