
2017年互联网秋招携程的笔试通知应该戳中过不少准备开发岗的同学。作为OTA赛道的头部玩家携程笔试当年的风格非常鲜明没有偏题怪题但覆盖面极广从Java基础到数据结构从数据库到网络协议几乎把一名开发工程师该有的基本功全部过了一遍。这份2017年校招开发工程师客观题汇总虽然过去了好几年但它所考察的知识点结构到今天仍然是技术面试的核心骨架。这篇文章我打算用工程师视角把这份考题背后的考察逻辑、高频考点和经典题型拆开揉碎讲一遍。已经上岸的可以当考古看看当年面试官的思路正在准备校招的可以把它当成一份复习提纲哪怕是准备社招用这些题自检基础是否扎实也很有价值。标题里写的是“客观题”但客观题往往才是整套笔试题的基座它决定了你能不能见到后面的算法题和开放性问答。1. 2017年携程校招笔试题全景解析1.1 当年的技术环境与开发工程师画像2017年是移动互联网红利期的尾巴智能手机普及率已经很高支付、出行、旅游这些线上化场景大规模成熟。携程的核心业务是机票、酒店、火车票、度假产品还有大量围绕旅行的内容和社区。竞争并不轻松飞猪、美团酒旅都在发力所以技术团队对工程师的要求非常实际来了就能干活基础要扎实。当时携程的技术栈以Java为主后端是SSM或类似的分层架构Spring Boot开始被越来越多团队采用服务化、消息队列、缓存、分库分表这些词在业务团队里已经非常高频。因此笔试不考具体框架而是考Java基础、并发、集合容器这些地基。开发工程师这个Title下不管是做后端、客户端还是前端第一轮客观题都绕不开计算机基础。这也解释了为什么题目里会出现大量Java题和数据库题——因为携程的核心业务链路里Java和MySQL就是主力军。值得注意的一个细节是2017年移动端开发岗位依然非常吃香Android和iOS原生开发需求旺盛。所以客观题里也会出现一些和客户端相关的考点比如多线程在UI场景下的使用、进程间通信、内存优化等。但整体来说基础题占大头业务框架题几乎没有。出题人默认你是一张白纸但白纸必须有过硬的基础素养。1.2 出题人的隐藏逻辑客观题为什么必要校招笔试收到的简历量是惊人的一个头部公司的技术岗热门城市笔试报名人数几千甚至上万根本不可能全安排面试。客观题就是第一道筛选漏斗量大、可机改、覆盖知识点广、没有主观争议。一道题该对就是对该错就是错省去了大量判卷成本也能快速把基础不扎实的人筛掉。但客观题有个天然缺陷——容易背题。所以出题人会在选项上做文章。比如题干问“以下说法错误的是”然后把两个只差一个字的知识点放在AB两个选项里专门区分背题的人和真正理解的人。还有一类经典陷阱是题干明明问的是“多选”但选项里混进一两个看起来正确、实际有前提条件才成立的表述只有对知识点掌握到细微层面的人才能全部选对。这也是为什么复盘这套题时不能只看正确答案要把每个错误选项为什么错也一并搞明白。2. 高频考点拆解这些题在考什么2.1 Java基础与并发业务架构的第一道门槛Java在2017年的互联网后端开发中占据绝对主导地位携程也不例外。笔试里的Java题重点集中在三个方向String与常量池、集合类HashMap、ArrayList、LinkedList、并发编程volatile、synchronized、线程池原理。先看String。字符串是实际开发中使用频率最高的对象但很多人在写业务时只关心值比较忽略了对象引用层面的差异。笔试中常出现的题目是用字面量创建的字符串和用new创建的字符串到底是不是同一个对象String的不可变性带来什么好处这些问题看起来偏冷但直接关系到JVM内存模型、常量池设计、缓存场景下对象的复用策略是一个很好的切入点。集合类更不用说了。HashMap的底层结构、哈希冲突的解决方式、扩容机制、为什么线程不安全都是客观题的常客。2017年这个时间点非常特殊因为JDK 1.8已经推出两年左右HashMap底层引入了红黑树很多人还在用1.7的思路答题这就形成了天然的区分度。通过一道关于链表转红黑树阈值的题出题人就能看出你是不是真的读过源代码。并发这个方向在携程的笔试里几乎必考。原因很简单一个每天处理海量订单和请求的系统处处都是并发场景机票库存的扣减、酒店房态的更新、优惠券的发放任何一个环节并发处理不当就会出现超卖或者重复发放的问题。客观题里关于并发考察最多的就是synchronized和volatile的区别、线程安全集合的选择、死锁的条件。这些知识点的背后考察的是你有没有并发编程时的微观思维。2.2 数据结构与算法客观题里的计算思维有人会觉得奇怪算法题怎么会用客观题来考不能写代码怎么考察编程能力实际上客观题里的算法考察的是另一层能力——对算法复杂度、数据结构性质、边界条件的理解。比如直接问你某种排序算法在平均情况下的时间复杂度或者给定一组操作问最终得到的数据结构形态。这些题目不需要你写代码但如果你没有真正理解算法的运作过程很难做对。2017年那会儿排序算法是笔试里的常青树。快排平均复杂度是O(n log n)最坏情况是O(n^2)堆排序时间复杂度始终是O(n log n)归并排序稳定快排不稳定这些点翻来覆去地考。表面上是在背性质实际上是要你理解分治、堆化、交换这些底层机制。当题目变成“在一个近乎有序的数组中哪个排序算法表现最好”就需要把插入排序的适应性也纳入考量了。数据结构方面链表、树、栈、队列是绝对主力。链表题喜欢考察插入删除的时间复杂度、与数组的对比树这一块则关注二叉树的遍历顺序——前序、中序、后序、层序之间的关系以及根据两种遍历序列能否唯一确定一棵二叉树的问题。这些都是裸考代码能力之前的“硬件自检”如果连遍历顺序都搞不清楚后面的代码题基本没法做。2.3 数据库与SQL订单系统的底层密码数据库题在携程笔试里的分量可能比很多人想象的还要重。携程的核心业务是交易撮合订单、支付、库存、价格每一环都是数据库操作的高频场景。答不好数据库题几乎等于对业务底层逻辑一无所知。2017年考察数据库的高频方向有四个索引结构、事务隔离级别、SQL执行顺序、范式与反规范化。索引结构几乎必考B树。为什么不是二叉树、不是哈希索引因为B树能够很好地支持范围查询和排序而且树的高度可控磁盘IO次数少。这些原理可能在面试时才问得更深但客观题里会考更直接的知识点比如“InnoDB默认隔离级别是哪一种”答案是可重复读。SQL执行顺序也是经典考点。很多人写SQL写得多但对底层执行顺序是一笔糊涂账。面试官只要稍微问一句“WHERE和HAVING哪个先执行”就能筛掉一批人。实际执行顺序是FROM、WHERE、GROUP BY、HAVING、SELECT、ORDER BY、LIMIT理解这个顺序对写优化SQL很有帮助尤其是嵌套子查询和聚合条件过滤的时候。范式与反规范化是另一个值得展开的点。校招笔试喜欢考判断某个表是否满足第三范式或者第几范式。而在这个题背后考察的是你有没有意识到数据库设计需要兼顾一致性、冗余和查询性能。到了实际业务里为了性能有时反规范化比教条式遵循范式更重要但前提是你得先理解范式在解决什么问题。2.4 操作系统与网络分布式场景的必修课后端开发离不开操作系统和网络。携程的线上服务是多机部署的一个请求要经过几十个服务的链式调用如果不懂进程线程、不懂TCP连接、不懂HTTP状态码排查线上问题会非常吃力。客观题在操作系统方向的考察主要围绕进程与线程、死锁条件、虚拟内存、进程间通信方式展开。进程与线程这对概念校招生最容易混淆。进程是资源分配的基本单位线程是CPU调度的基本单位同一进程内的线程共享地址空间而进程之间拥有独立的地址空间。这些基础概念看起来简单但一旦结合“线程安全”这个概念很多人就开始犯迷糊线程之间共享哪些资源局部变量是否线程安全在Java里局部变量存放在虚拟机栈中属于线程私有所以局部变量天然不存在共享问题。这个推导过程其实就是面试官想看到的思维路径。网络协议方面TCP三次握手和四次挥手是必考中的必考。题目不会只问次数还会问每个状态的名字尤其是在TIME_WAIT这个状态下出的题特别多。为什么要等待2MSL因为要保证最后一次ACK能被对方收到以及让旧连接的数据包在网络中自然消失。另外HTTP状态码也会考比如301和302的区别、401和403的差异、500和502的不同。这些状态码背后的语义直接影响接口调用的容错策略。3. 2017年携程开发岗笔试客观题模拟复盘下面这一组题目是根据当年主流校招笔试的考察角度和知识密度整理出来的风格化复盘题目的不是还原某一份真实试卷而是帮大家重新回到那套考试逻辑里感受每一类问题背后的考察点。我按模块拆开讲每题都给出解析尤其是易错选项的坑。3.1 Java基础与底层原理风格题单选题 1String s1 abc; String s2 abc; String s3 new String(abc); System.out.println(s1 s2); System.out.println(s1 s3);以上代码的输出结果为A. true trueB. true falseC. false trueD. false false这道题考察的是字符串常量池与对象引用的区别。s1和s2都是字符串字面量编译期间会存放在常量池中所以它们指向同一个字符串对象s1 s2的结果是true。s3是使用new关键字在堆上新建的对象即使字面量相同引用地址也不一样所以s1 s3的结果是false。答案是B。这道题真正想考的是常量池机制以及你是否记得使用equals做内容比较。延伸考点是intern方法它能将堆中的字符串对象在必要时加入常量池并返回常量池引用理解这一点对JVM调优和内存分析有一定帮助。单选题 2Integer a 100; Integer b 100; Integer c 128; Integer d 128; System.out.println(a b); System.out.println(c d);A. true trueB. true falseC. false trueD. false false这道题目的坑在于自动装箱。Integer在缓存范围内会复用对象JDK默认的缓存范围是-128到127。所以100在缓存内a和b指向同一个Integer对象a b为true128超出缓存c和d各自new了对象c d为false。答案是B。这种题在实际编码中很容易踩坑尤其是把Integer当作Map的key或者放进集合里比对时不小心用了就会得到意想不到的结果。顺带说一句自动拆箱时如果包装类型为nullNPE是跑不掉的这也是研发新人经常遇到的基础问题。单选题 3在JDK 1.7中HashMap在并发环境下执行put操作并触发扩容时最经典的问题是A. 数据直接丢失但不影响后续操作B. 链表形成环导致后续get操作死循环C. HashMap会自动加锁保证线程安全D. 抛出NullPointerException答案是B。JDK 1.7的HashMap扩容采用头插法转移节点当多个线程同时触发扩容时可能存在两个线程同时操作同一个链表形成循环引用后续在get时遍历这个环形链表就会死循环。这个Bug是当年并发编程考题里的经典素材也是为什么后来JDK 1.8将链表插入方式改为尾插法并加入红黑树优化的原因之一。这道题考察的深度其实不低如果只看过1.8的源码可能根本不知道头插法的问题所以在当年是一个明显的区分点。3.2 数据结构与算法风格题单选题 4已知一棵二叉树的前序遍历序列为ABDCE中序遍历序列为DBACE则这棵二叉树的后序遍历序列为A. DBECAB. DECBAC. DBCEAD. EDBCA这是一道非常经典的由前序和中序推后序的题。由前序遍历可知根节点是A在中序遍历中找到A的位置A左侧的DB是左子树右侧的CE是右子树。继续拆分前序第二个节点是B说明左子树的根是B再结合中序D在B左侧可以推出D是B的左孩子。右侧同理前序第四个节点是C中序C在E的左侧所以E是C的左孩子。最终可得后序遍历为DBECA答案是A。这类题考的是对三种遍历顺序的递归定义是否真正理解而不是死记序列。实际手算时我习惯先把树形结构画出来再输出后序序列正确率会高很多。单选题 5快速排序在平均情况和最坏情况下的时间复杂度分别是A. O(n log n)O(n log n)B. O(n log n)O(n^2)C. O(n^2)O(n^2)D. O(n log n)O(n)答案是B。快速排序在平均情况下每次划分都把数组分成大致相等的两部分递归树的深度是log n每层处理n个元素所以总复杂度是O(n log n)。最坏情况是每次划分都极度不平衡比如对一个已经有序的数组升序排序且每次选第一个元素作为基准分割出来的两个子序列长度悬殊递归深度变成n复杂度退化为O(n^2)。理解“平均”和“最坏”的区别对选择排序算法非常有帮助。实际业务中如果数组规模大且数据基本有序直接使用基础快排可能性能很差这时候需要引入随机化基准或者三数取中法来优化。3.3 数据库与SQL风格题单选题 6在MySQL的InnoDB存储引擎中默认的事务隔离级别是A. READ UNCOMMITTEDB. READ COMMITTEDC. REPEATABLE READD. SERIALIZABLE答案是C。MySQL的InnoDB默认隔离级别是可重复读而Oracle等数据库默认是读已提交。这个差异是很多跨数据库经验的同学容易记混的地方。可重复读隔离级别下同一个事务内多次读取同一行数据结果始终是一致的这由MVCC多版本并发控制的快照机制来保证。可能有人问那幻读问题怎么办InnoDB在可重复读级别下通过Next-Key Lock间隙锁加记录锁的组合在一定程度上解决了幻读问题这也是为什么MySQL默认选择可重复读的底气所在。这道题表面考的是一个默认值实际上在考你对隔离级别演进和MVCC机制的理解。单选题 7有表t包含字段a和b执行语句如下ALTER TABLE t ADD INDEX idx_a_b (a, b); SELECT * FROM t WHERE a 1 AND b 2; SELECT * FROM t WHERE b 2;以下说法正确的是A. 两条SQL都能命中联合索引idx_a_bB. 第一条SQL能命中联合索引第二条SQL无法命中C. 第一条SQL无法命中联合索引第二条SQL能命中D. 两条SQL都无法命中联合索引答案是B。联合索引遵循最左前缀原则。idx_a_b以a列作为最左列查询条件中如果包含a则无论b是否参与都能使用该索引最左部分但如果条件中没有a只有b就无法使用这个联合索引。注意第一条SQL中“a 1 AND b 2”的顺序并不重要MySQL优化器会做语义分析不一定按照书写顺序来匹配索引。这条题目考察的核心是索引设计意识联合索引的列顺序决定了它能覆盖哪些查询组合。在建索引时需要把等值查询频率最高、选择性最好的列放在最左边。3.4 操作系统与网络风格题多选题 8下列关于TCP连接的说法正确的是A. TCP建立连接需要三次握手B. TCP断开连接需要四次挥手C. TCP是面向连接的可靠传输协议D. TCP首部长度固定为20字节答案是A、B、C。TCP是面向连接的可靠传输协议建立连接需要三次握手断开连接需要四次挥手这两点是答网络题的基本功。D选项是干扰项TCP首部长度是可变的基础固定部分是20字节但如果有选项字段长度会超过20字节所以不能说固定为20字节。这个细节很容易被忽略出题人就是故意用一个“基本正确但细节错误”的选项来筛人。三次握手的核心是确认双方的收发能力四次挥手是因为TCP连接是全双工的每一方的关闭都需要独立确认。多选题 9关于进程和线程下列说法正确的是A. 进程是资源分配的基本单位线程是CPU调度的基本单位B. 同一进程内的线程共享进程的地址空间C. 不同进程之间拥有独立的地址空间进程间通信需要通过专门的机制D. 线程可以完全脱离进程独立运行答案是A、B、C。进程拥有独立的地址空间线程共享进程的地址空间这是两者最本质的区别之一。D选项错误线程是进程中的一个执行单元不能完全脱离进程独立存在。进程间通信的常见方式包括管道、消息队列、共享内存、信号量、Socket等。这类题在2017年不仅出现在笔试中后续的面试里被追问的概率也非常高答到“为什么线程切换成本比进程切换低”这个层面基本就能让面试官认可你的操作系统功底了。4. 从一套真题看备战策略与今天的面试演化4.1 如果回到2017这套题应该怎么刷把这套客观题复盘一遍之后你会发现它其实不是一个“背题就能过”的考试。它的知识密度和交叉性非常强每一道题背后都能扩展出一整个知识面。如果让我回到2017年重新备考我会按三个阶段来刷题。第一阶段是基础扫描期时长约一周。先把计算基础全部过一遍包括Java核心、数据机构与算法、数据库、操作系统、计算机网络。这个阶段不追求深度重点是建立完整的知识树。每一个知识点至少要知道“是什么”和“为什么存在”。比如看到B树至少要能说出它和普通二叉搜索树、哈希索引的区别而不是只记住“数据库索引用的是B树”这个结论。第二阶段是专项突破期时长约两周。根据第一阶段暴露出来的薄弱环节对照一套真题逐题分析考点把每一道错题的错误选项都弄清楚。这个阶段我推荐用表格来整理复习卡片效果非常好。我自己当年整理的卡片长这样题目类型高频考点一句话原理易错点Java基础字符串常量池字面量复用new重新创建用比较引用而非内容Java并发HashMap扩容死循环头插法导致链表成环忽略JDK版本差异数据结构快排复杂度分治平均log n最坏退化为n混淆平均与最坏区别数据库联合索引最左前缀索引列顺序决定匹配范围忽略优化器对条件顺序的调整网络TCP状态变化三次握手建连四次挥手断连TIME_WAIT存在意义第三阶段是模拟冲刺期考前三天集中做套题。不用贪多每天一到两套严格按照时间限制来。客观题部分一般要求在30到40分钟内完成如果某道题超过三分钟还没思路就先标记跳过等全部做完再回头处理。这个习惯不仅适用于笔试也非常适用于面试中的白板编程环节。4.2 经典考点与AI应用开发工程师的今天把2017年的这套题目放到今天来看有一个明显的感受开发工程师的岗位分得越来越细从当年相对通用的“开发工程师”演化出了AI应用开发工程师、大模型全栈工程师、智能体开发工程师等细分方向。很多人会问AI应用开发工程师需要具备什么样的能力是不是不再需要传统笔试里的那些底层基础了我的答案是恰恰相反。AI应用开发工程师不是只写Prompt或者调用API的岗位。它依然要求扎实的工程能力只不过把传统能力应用到了新的场景里。比如要用Python还是Java做服务框架遇到性能瓶颈时怎么排查数据存储怎么设计这些都需要计算机基础做支撑。大模型全栈工程师更是如此既要懂模型输入输出的处理也要懂上层应用的架构和部署本质上还是全栈开发能力加上AIGC领域知识的组合。智能体开发工程师则需要理解任务拆分、工具调用、上下文管理这些偏上层应用设计的思维但底层的并发处理、API通信、数据流转依然是逃不开的基本功。所以如果你现在正在准备校招看到AI应用开发工程师这类新岗位不要被“新”字吓住。把这个岗位描述拆开来看里面仍然大量依赖数据结构、数据库、网络协议、操作系统这些经典考点。2017年携程这套客观题里的知识点放到今天依然是技术面试的重要骨架只不过出题背景可能从酒店订单变成了智能体调度从机票库存变成了模型接口限流。变化的只是业务场景底层原理没有变。4.3 客观题的临场答题技巧笔试和面试不一样它没有临场沟通的机会每一道题都只能凭直觉和经验作答。所以掌握一些客观题的通用技巧能帮你减少不必要的失分。第一个技巧是时间分配。正式笔试的客观题部分一般每道题平均只有一分多钟。碰到一个完全不认识的知识点不要恋战直接先跳过。客观题的计分规则通常是答对得分、不答不得分与其在一道题上耗五分钟不如把省下来的时间用在后面有把握的题上。很多在线笔试平台支持标记题目做完一轮后回头再处理标记题可能因为后面的题目触发了记忆原本不会的题也能找到突破口。第二个技巧是排除法加极限思维。针对没有十足把握的单选可以通过排除确定错误的选项来提升正确率。比如遇到关于时间复杂度的选项可以代入极端情况来验证输入规模是1时结果是多少输入规模非常大时结果是否会失控。这种思路在计算类题目中特别有效。而遇到多选题策略就要保守一些宁可少选不要多选。当年不少校招笔试多选题采用漏选得部分分、错选不得分的规则如果看不准某个选项就不应该冒险勾上。第三个技巧是审题时把“错误的”和“正确的”圈出来。客观题经常出现“以下说法错误的是”这种反向提问很多同学做习惯了正向选择看到正确答案就直接选结果题干问的是错误选项一不留神就失分了。我当年的习惯是在草稿纸上先写出“要求选正确还是错误”再逐项核对做完后再回头检查一遍确保没有理解偏差。还有一个容易被忽视的细节答题时不要频繁修改答案。第一直觉往往是基于最扎实记忆的反应除非你明确发现自己最开始看错了题干否则不要因为纠结而改成另一个模棱两可的选项。我见过身边太多同学考试结束时把原本正确的答案改错了走出考场才追悔莫及。这份2017年的题目跟着我搬了两次电脑后来又在我的书签里躺了几年。前阵子帮一个学弟梳理面试题我又把它翻了出来。最大的感受是题目会过时但考点不会。当年HashMap那条链表成环的题今天依然有很多人在并发编程上栽跟头当年那道TCP四次挥手今天微服务调用失败时排查思路还是它。如果你正在准备任何一场技术面试与其刷一堆浮于表面的面经不如静下心来把这些经典基础题一道道吃透。工具和框架会变底层思维不会。最后分享一个我自己复盘笔试题的小习惯把错题整理成一张表左边是题目右边是考点和一句话原理不需要长篇大论。考前看这张表比临时翻书有用得多。