ARTICLE · 1268789
面试官问"AI能写80%代码了,Java程序员还需要会什么"?我面了20个人后的真实答案
最近"AI能写80%的代码了,公司为什么还需要你"这个话题特别火,后台好几个读者给我留言,说面试被问到这个问题,当场就懵了。
说实话,这个问题我也被问过,只不过我是坐在面试官那一侧。
上个月帮团队面了20个Java开发,中级高级都有。我特意在每场面试里加了一个环节:给候选人一段AI生成的代码,让他找问题。结果挺有意思的,20个人里能找出关键问题的不到5个。
所以今天不聊虚的,就聊点实在的:AI确实能写80%的代码,但剩下那20%,恰恰是公司愿意给你开工资的部分。这篇是我面完20个人之后的真实总结,也是我自己带团队这些年的体会。
先说结论:AI写代码,强在"形似",弱在"神似"。它能给你一个看起来能跑的SpringBoot接口,但它不知道这个接口在高并发下会不会把数据库打挂。
下面我分几个方面,结合具体的Java技术点,跟你说清楚到底还差什么。
第一步:先搞清楚AI到底能写什么、写不好什么
很多人对AI编程有误解,要么觉得它无所不能,要么觉得它一无是处。都不对。
我拿一个真实的例子给你看。我让AI写一个"用户下单扣库存"的接口,它给我的代码大概是这样:
@RestController@RequestMapping("/order")public class OrderController { @Autowired private OrderService orderService; // 下单接口 @PostMapping("/create") public Result createOrder(@RequestBody OrderDTO orderDTO) { return orderService.createOrder(orderDTO); }}@Servicepublic class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private StockMapper stockMapper; // 创建订单:先查库存,再扣减,再插订单 @Transactional public Result createOrder(OrderDTO orderDTO) { // 1. 查询库存 Stock stock = stockMapper.selectByProductId(orderDTO.getProductId()); if (stock.getCount() < orderDTO.getNum()) { return Result.fail("库存不足"); } // 2. 扣减库存 stock.setCount(stock.getCount() - orderDTO.getNum()); stockMapper.updateById(stock); // 3. 生成订单 Order order = new Order(); order.setProductId(orderDTO.getProductId()); order.setNum(orderDTO.getNum()); orderMapper.insert(order); return Result.success(order); }}看着挺像回事吧?注解齐全,注释清晰,逻辑通顺。一个新手看到这段代码,可能直接就复制进项目了。
但这段代码放到生产环境,是要出事的。我把它拆开讲。
第二步:AI写不对的地方之一——并发和超卖
上面那段代码最大的问题,是"先查库存、再扣库存"这个动作不是原子的。两个人同时下单,都查到库存是10,都判断"库存够",然后都扣减,最后库存变成8,但实际卖出去20件。这就是经典的超卖问题。
你问AI"这样写有并发问题吗",它有时候能答上来,但它默认给你的代码就是这么写的。因为AI学的是"最常见的写法",而最常见的写法往往不是"最正确的写法"。
正确的做法至少有三种,你得知道什么时候用哪种:
乐观锁的写法大概是这样:
// StockMapper.xml 里的 SQL,注意 where 条件里带了 count 判断// update stock set count = count - #{num} where product_id = #{productId} and count >= #{num}@Transactionalpublic Result createOrder(OrderDTO orderDTO) { // 直接扣减,SQL 的 where 条件保证不会超卖 int affected = stockMapper.deductStock(orderDTO.getProductId(), orderDTO.getNum()); // 影响行数为 0,说明库存不足,扣减失败 if (affected == 0) { return Result.fail("库存不足"); } // 扣减成功再生成订单 Order order = new Order(); order.setProductId(orderDTO.getProductId()); order.setNum(orderDTO.getNum()); orderMapper.insert(order); return Result.success(order);}这段代码的关键,是把"判断"和"扣减"合并成一条SQL,交给数据库来保证原子性。这个思路AI不会主动给你,因为它不理解你的业务场景有多高的并发。
面试的时候,我问"这段代码有什么问题",能说出超卖的候选人,我基本就给他打了及格分。因为这个点考的不是记忆力,是你有没有真的在生产环境踩过坑。
第三步:AI写不对的地方之二——Spring事务的坑
还是上面那段代码,加了@Transactional就万事大吉了吗?不是。
我见过太多人以为加了@Transactional就自动回滚,结果出了事才发现没生效。AI生成的代码里,@Transactional几乎是标配,但它不会告诉你这个注解有几个大坑。
第一个坑:异常被吞了,事务不回滚。默认情况下,Spring只对RuntimeException回滚,你如果抛的是受检异常,或者自己catch了没往外抛,事务是不会回滚的。
@Transactionalpublic void createOrder(OrderDTO dto) { try { // 扣库存 stockMapper.deductStock(dto.getProductId(), dto.getNum()); // 这里如果抛异常,被 catch 住了,事务不会回滚 orderMapper.insert(buildOrder(dto)); } catch (Exception e) { // 吞掉异常,事务照常提交,数据就脏了 log.error("下单失败", e); }}第二个坑:同类内部调用,事务失效。你在A方法里调用同一个类里的B方法,B方法上的@Transactional是不生效的,因为没走代理。
第三个坑:事务里做了远程调用或者慢操作,把数据库连接占着不放,高并发下连接池直接被耗尽。
这些问题,AI写代码的时候不会提醒你。你问它,它可能答得头头是道,但它默认生成的代码就是有这些隐患。所以"能看懂AI写的代码有没有坑",比"能让AI写出代码"值钱得多。
第四步:AI写不对的地方之三——SQL和索引
再说一个我面试必问的点:慢SQL。
AI写MyBatis的Mapper,经常给你写出这种SQL:
<!-- 模糊查询,前面带 %,索引直接失效 --><select id="searchByName" resultType="User"> select * from user where name like concat('%', #{name}, '%')</select>或者这种:
<!-- 对字段做了函数运算,索引失效 --><select id="findByDate" resultType="Order"> select * from orders where date_format(create_time, '%Y-%m-%d') = #{date}</select>这两条SQL在数据量小的时候跑得飞快,数据量上到百万级,就是线上事故。AI不会管这些,它只管"这条SQL能不能查出结果"。
你要会的是:知道like '%xx%'用不上索引、知道字段上做函数运算用不上索引、会用explain看执行计划、知道联合索引的最左前缀原则。
我给你一个能直接用的排查套路:
-- 1. 先看执行计划,重点看 type 和 rowsexplain select * from orders where user_id = 1001;-- 2. type 出现 ALL 说明全表扫描,要警惕-- 3. rows 很大说明扫描行数多,要考虑加索引-- 4. 确认索引是否命中,看 key 字段这些是"AI能写SQL,但写不出好SQL"的地方。你要做的是那个能判断SQL好坏的人。
第五步:那Java程序员到底还要会什么
聊了这么多具体的坑,我总结一下。AI时代,Java程序员的核心竞争力,我认为是这三样。
第一,会判断。AI给你一段代码,你要能一眼看出它在并发、事务、SQL、异常处理上有没有问题。这个能力来自你对JVM、并发、数据库这些底层知识的理解,不是来自你会不会用AI。
第二,会设计。AI能写单个接口,但它设计不了一个能扛住流量洪峰的系统。分库分表怎么分、缓存怎么用、消息队列怎么削峰、服务怎么拆分,这些是架构层面的判断,AI给不了你答案,因为它不知道你的业务量级和团队情况。
第三,会兜底。线上出问题了,CPU飙到100%、接口大面积超时、数据库连接池打满,这时候AI帮不了你,得靠你看日志、看线程栈、看GC情况,一步步定位。我见过太多人,代码写得挺溜,一出问题就抓瞎。
# 线上排查常用的几个命令,你得会# 1. 看Java进程jps -l# 2. 看线程栈,找卡住的线程jstack <pid> > thread.log# 3. 看GC情况jstat -gcutil <pid> 1000# 4. 看堆内存对象分布jmap -histo <pid> | head -20这些命令,AI能告诉你用法,但真到线上那一刻,敢不敢敲、敲完能不能看懂,是你自己的事。
写在最后
回到面试官那个问题:"AI能写80%的代码了,公司为什么还需要你?"
我现在的答案是:因为那80%的代码,总得有人来判断它能不能上线。AI是个很强的执行者,但它不是个能担责任的工程师。代码出了事故,背锅的是人,不是AI。
所以别焦虑,也别躺平。把JVM、并发、数据库、Spring这些基本功打扎实,把AI当成一个效率工具用起来,你不但不会被替代,反而会比以前更值钱。因为以前你要花80%的时间写那些重复代码,现在你可以把时间花在真正重要的20%上。
最后问你一句:你平时用AI写代码,有没有遇到过它给你挖坑的情况?评论区聊聊,我看看大家踩的坑是不是都差不多。
下一篇我打算写"SpringBoot接口性能优化的几个实操手段",从慢SQL到连接池配置,都是能直接落地的,感兴趣的点个关注别错过。















































































