导语
同一道 Java 后端真题,三个模型同时作答。从代码质量、架构思维、中文理解、成本四维度打分,给出选型决策树。
测试时间 :2026 年 5 月
测试模型 :Claude Sonnet 4.6、GPT-5.5、DeepSeek V4
测试方式:统一 Prompt,独立调用,人工评分
一、测试规则设定
1.1 评分维度与权重
| 维度 | 权重 | 评分标准 |
|---|---|---|
| 代码正确性 | 30% | 是否能运行、有无明显 Bug |
| 架构深度 | 25% | 是否考虑扩展性、性能、安全 |
| 中文表达 | 15% | 注释、文档是否自然流畅 |
| 响应速度 | 15% | 首次响应时间 |
| 调用成本 | 15% | 每 1K tokens 价格 |
1.2 测试题目设计
题目 1:复杂业务代码生成(权重 40%)
需求:设计一个带事务、缓存、消息通知的订单状态机。订单状态:CREATED → PAID → SHIPPED → COMPLETED。要求:
- 状态流转必须校验前置状态;
- 支付成功后发 MQ 通知库存扣减;
- 每个状态变更记流水;
- 支持幂等(同一订单同一状态只处理一次)。
题目 2:Bug 修复(权重 30%)
给一段真实 NPE + 并发问题的代码,要求定位根因并给出修复方案。
题目 3:架构设计(权重 30%)
需求:设计一个高并发库存扣减方案(10万 QPS),要求:
- 不能超卖;
- 响应时间 < 50ms;
- 支持多仓库;
- 考虑降级方案。
二、题目 1:复杂业务代码生成
2.1 统一 Prompt
你是一名资深 Java 后端开发工程师。
请实现一个订单状态机服务,要求:
1. 状态:CREATED, PAID, SHIPPED, COMPLETED, CANCELLED
2. 状态流转规则:CREATED→PAID→SHIPPED→COMPLETED;CREATED→CANCELLED;PAID→CANCELLED(需退款)
3. 支付成功后异步发送 MQ 消息通知库存服务
4. 每个状态变更记录流水(who, when, from, to, reason)
5. 幂等控制:同一订单同一目标状态只能成功一次
6. 使用 Spring Boot + MyBatis-Plus + PostgreSQL + RabbitMQ
7. 输出完整可运行的 Java 代码(含 Entity、Service、Mapper、MQ 配置)
2.2 Claude Sonnet 4.6 输出
亮点:
- 使用了状态模式(State Pattern)+ 策略模式,扩展性好
- 幂等控制用数据库唯一索引(order_id + target_status)
- MQ 发送失败有重试机制(Spring Retry)
- 事务边界清晰:状态更新 + 流水记录在同一个 @Transactional 内
代码片段(节选):
java
@Component
@RequiredArgsConstructor
public class OrderStateMachine {
private final Map<OrderStatus, List<OrderStatus>> transitions = Map.of(
CREATED, List.of(PAID, CANCELLED),
PAID, List.of(SHIPPED, CANCELLED),
SHIPPED, List.of(COMPLETED)
);
public boolean canTransition(OrderStatus from, OrderStatus to) {
return transitions.getOrDefault(from, List.of()).contains(to);
}
}
@Service
@RequiredArgsConstructor
@Slf4j
public class OrderServiceImpl implements OrderService {
private final OrderMapper orderMapper;
private final OrderFlowRecordMapper flowMapper;
private final RabbitTemplate rabbitTemplate;
private final OrderStateMachine stateMachine;
private final RedissonClient redissonClient;
@Override
@Transactional(rollbackFor = Exception.class)
public void transition(Long orderId, OrderStatus targetStatus, String operator) {
String lockKey = "order:transition:" + orderId;
RLock lock = redissonClient.getLock(lockKey);
try {
if (!lock.tryLock(5, 30, TimeUnit.SECONDS)) {
throw new BizException("订单处理中,请稍后再试");
}
Order order = orderMapper.selectById(orderId);
if (order == null) {
throw new BizException("订单不存在");
}
// 1. 校验状态流转合法性
if (!stateMachine.canTransition(order.getStatus(), targetStatus)) {
throw new BizException(
String.format("非法状态流转: %s -> %s", order.getStatus(), targetStatus));
}
// 2. 幂等校验:已到达目标状态
if (order.getStatus() == targetStatus) {
log.warn("订单{}已经是目标状态{},跳过处理", orderId, targetStatus);
return;
}
OrderStatus fromStatus = order.getStatus();
// 3. 更新状态(乐观锁)
int affected = orderMapper.updateStatus(orderId, targetStatus, fromStatus, order.getVersion());
if (affected == 0) {
throw new BizException("订单状态已变更,请刷新后重试");
}
// 4. 记录流水
OrderFlowRecord record = new OrderFlowRecord();
record.setOrderId(orderId);
record.setFromStatus(fromStatus);
record.setToStatus(targetStatus);
record.setOperator(operator);
record.setCreatedAt(LocalDateTime.now());
flowMapper.insert(record);
// 5. 支付成功发 MQ
if (targetStatus == PAID) {
sendInventoryDeductMessage(order);
}
// 6. 取消订单需退款
if (targetStatus == CANCELLED && (fromStatus == PAID || fromStatus == SHIPPED)) {
sendRefundMessage(order);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new BizException("系统繁忙");
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
private void sendInventoryDeductMessage(Order order) {
try {
rabbitTemplate.convertAndSend(
"order.exchange",
"order.paid",
new InventoryDeductEvent(order.getId(), order.getItems()),
message -> {
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
return message;
}
);
} catch (AmqpException e) {
log.error("发送库存扣减消息失败, orderId={}", order.getId(), e);
// 记录待补偿任务,由定时任务重试
saveCompensateTask(order.getId(), "INVENTORY_DEDUCT");
}
}
}
评分 :代码正确性 28/30,架构深度 23/25,中文表达 14/15,响应速度 13/15,成本 10/15(较贵)。总分:88/100
2.3 GPT-5.5 输出
亮点:
- 代码更简洁,直接状态机用枚举实现
- 异常处理更细致(每种异常都有独立异常类)
- 使用了 Spring 的事件机制(ApplicationEvent)解耦 MQ 发送
不足:
- 幂等控制用 Redis SETNX,没有数据库唯一索引兜底,极端场景可能重复
- 事务范围过大(MQ 发送在事务内,若 MQ 超时会导致事务回滚)
评分 :代码正确性 26/30(幂等方案有瑕疵),架构深度 22/25,中文表达 13/15,响应速度 14/15,成本 12/15。总分:87/100
2.4 DeepSeek V4 输出
亮点:
- 代码量最大,注释最详细(几乎每行都有注释)
- 考虑了监控埋点(Micrometer Metrics)
- 使用了 CompletableFuture 做异步流水记录
不足:
- 过度设计:用了责任链模式处理状态流转,一个小项目搞得太复杂
- 并发控制只有乐观锁,没有分布式锁,高并发可能冲突频繁
- 中文注释有「机翻」感
评分 :代码正确性 25/30(并发控制不足),架构深度 21/25(过度设计),中文表达 11/15,响应速度 12/15,成本 15/15(最便宜)。总分:84/100
三、题目 2:Bug 修复
3.1 题目代码
java
@Service
public class InventoryService {
@Autowired
private InventoryMapper inventoryMapper;
@Autowired
private RedisTemplate<String, Integer> redisTemplate;
public boolean deduct(String drugId, int quantity) {
// 先查缓存
Integer stock = redisTemplate.opsForValue().get("stock:" + drugId);
if (stock == null) {
// 缓存未命中,查数据库
stock = inventoryMapper.selectStock(drugId);
redisTemplate.opsForValue().set("stock:" + drugId, stock, 5, TimeUnit.MINUTES);
}
if (stock >= quantity) {
// 扣减库存
int newStock = stock - quantity;
redisTemplate.opsForValue().set("stock:" + drugId, newStock);
// 异步更新数据库
new Thread(() -> {
inventoryMapper.updateStock(drugId, newStock);
}).start();
return true;
}
return false;
}
}
3.2 三个模型的诊断对比
| Bug | Claude 4.6 | GPT-5.5 | DeepSeek V4 |
|---|---|---|---|
| NPE 风险 | ✅ 指出 stock 可能为 null(数据库无记录) |
✅ 指出 | ✅ 指出 |
| 并发安全问题 | ✅ 指出「先读缓存再判断」非原子操作,并发下超卖 | ✅ 指出 | ⚠️ 只提到「建议加锁」,没点破原子性问题 |
| 缓存一致性 | ✅ 指出「异步线程更新数据库失败导致缓存与 DB 不一致」 | ✅ 指出 | ✅ 指出 |
| 线程池滥用 | ✅ 指出 new Thread() 无界创建,应该用线程池 |
✅ 指出 | ❌ 未提及 |
| 事务缺失 | ✅ 指出无 @Transactional,DB 更新失败无回滚 | ✅ 指出 | ✅ 指出 |
| 修复方案质量 | 给出 Redisson + Lua 原子扣减 + 事务 + 线程池的完整方案 | 类似,但用 synchronized(不够) | 给出 SETNX 锁(正确但性能差) |
评分:Claude 4.6 29/30,GPT-5.5 27/30,DeepSeek V4 24/30。
四、题目 3:架构设计
4.1 需求
设计一个高并发库存扣减方案(10万 QPS),要求不能超卖、响应时间 < 50ms、支持多仓库、考虑降级方案。
4.2 三个模型的方案对比
| 维度 | Claude 4.6 | GPT-5.5 | DeepSeek V4 |
|---|---|---|---|
| 核心方案 | Redis Lua 原子扣减 + 异步刷库 + 多级缓存 | 类似,但加「库存分段」思想 | Redis 扣减 + 消息队列异步 |
| 多级缓存 | L1 Caffeine(本地)+ L2 Redis(分布式) | 只有 Redis | 只有 Redis |
| 分段锁 | 提到「按仓库+药品哈希分段」 | 详细设计「库存分段」方案 | 未提及 |
| 降级方案 | 三级降级:缓存扣减 → DB 扣减 → 拒绝服务 | 两级降级 | 一级降级(直接拒绝) |
| 监控告警 | 包含 QPS/RT/错误率/库存偏差监控 | 包含基础监控 | 未提及 |
| 兜底方案 | 定时对账 + 库存补偿任务 | 提到对账 | 未提及 |
评分:Claude 4.6 24/25,GPT-5.5 22/25,DeepSeek V4 19/25。
五、综合评分表
| 维度 | Claude Sonnet 4.6 | GPT-5.5 | DeepSeek V4 |
|---|---|---|---|
| 代码正确性 (30%) | 28 | 26 | 25 |
| 架构深度 (25%) | 23 | 22 | 21 |
| 中文表达 (15%) | 14 | 13 | 11 |
| 响应速度 (15%) | 13 | 14 | 12 |
| 调用成本 (15%) | 10 | 12 | 15 |
| 总分 | 88 | 87 | 84 |
雷达图描述
- Claude 4.6:代码正确性和架构深度最强,但成本最高,适合复杂业务场景
- GPT-5.5:最均衡,响应最快,适合日常编码和快速迭代
- DeepSeek V4:成本最低,性价比最高,适合预算敏感团队和基础任务
六、选型决策树
你的场景是什么?
│
├── 复杂架构设计 / 核心模块开发 ──→ Claude Sonnet 4.6
│
├── 日常接口开发 / 快速原型 ───────→ GPT-5.5
│
├── 预算敏感 / 团队共享 ───────────→ DeepSeek V4
│
├── 隐私敏感 / 数据不出内网 ───────→ 本地 DeepSeek / Ollama
│
└── 代码 Review / 报错分析 ────────→ Claude 4.6(最细致)
我的实际用法
| 任务 | 选用模型 | 原因 |
|---|---|---|
| 新模块架构设计 | Claude 4.6 | 架构思维最强 |
| 日常 CRUD 接口 | GPT-5.5 | 速度快、成本低 |
| SQL 生成 / 简单重构 | DeepSeek V4 | 性价比最高 |
| 代码 Review | Claude 4.6 | Bug 找得最细 |
| 报错分析 | Claude 4.6 | 解释最清晰 |
| 批量生成单元测试 | GPT-5.5 | 批量调用成本低 |
写在最后
三个模型各有千秋,没有「最好」,只有「最合适」。我的建议是:
- 至少订阅两个模型(一个主力 + 一个备用),防止某个模型「抽风」
- 复杂任务用 Claude,简单任务用 DeepSeek,成本能降 70%
- 定期重新评估:大模型迭代很快,今天的结论下个月可能就变了
关注【魔法数字】,更多技术干货等你来发掘。