基本类型适用于确定且不可空的数值语义,如超时毫秒数;包装类型仅用于需三态语义(未设置/无效/显式值)场景;引用类型应封装逻辑相关字段为POJO或record,并注意边界层装箱与对象污染风险。

API 方法传参时,基本类型和引用类型的选用不是语法习惯问题,而是接口契约是否清晰、调用是否安全的关键判断。
基本类型适合表达确定、不可空的数值语义
当参数代表明确且必须提供的量时(如重试次数、超时毫秒数、状态码),直接使用 int、long、boolean 等基本类型:
- 天然不可为 null,避免客户端传 null 导致 NPE 或逻辑歧义
- JSON 序列化稳定:{"timeout": 5000} 比 {"timeout": null} 更易被前端解析和校验
- 配合 @NonNull 或 Lombok @RequiredArgsConstructor,可在编译期强化非空约束
- 不建议用 int 表达“可选默认值”场景——这时应换思路,比如拆出独立的 boolean useDefaultTimeout
包装类仅用于需要三态语义或参与泛型
只有真正需要区分“未设置 / 无效 / 显式值”三种状态时,才用 Integer、Boolean 等:
- 分页参数 Integer pageSize 可表示“不传即用默认”,而 int 强制传值,无法表达该意图
- 所有包装类反序列化失败时可能为 null,服务端必须主动判空并返回 400 错误(如 "limit must be a valid integer")
- 避免混用:同一业务字段(如 age)在不同接口中一会儿是 int,一会儿是 Integer,会破坏契约一致性
- 注意缓存范围:Integer == 比较仅在 -128~127 安全,一律用 .equals()
引用类型用于封装资源、关系与可扩展结构
多个逻辑相关的字段不应拆成一堆独立参数,而应封装为 POJO 或 record:
- 把 String name, String email, int age 合并为 UserInput 类,便于加 @NotBlank、@Email 等校验
- 响应体优先返回领域对象(如 Order),而非通用 wrapper(如 {code:0,data:{}})
- 嵌套结构只用于自然归属关系(如 Order 包含 List<OrderItem>),避免深层路径(user.profile.settings.theme)
- 新增字段必须设为 optional,删除或重命名字段需升版本隔离,防止破坏现有客户端
边界层要警惕隐式装箱与对象污染
Controller 层、RPC 入参、JSON 序列化是风险高发区:
- 不要将数据库实体直接返回,需 clean mapping 剥离敏感字段(如 _id、password)
- 接收引用类型参数后,勿直接复用或缓存原始对象,防止状态意外修改
- 前端 SDK 接收响应后建议做浅拷贝,避免后续操作污染原始数据
- 禁止在 DTO 中同时暴露 int 和 Integer 表达同一含义,统一类型才能保障契约可演进

















