ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

百度2020校招Java笔试卷深度解析:核心考点与解题思路

百度2020校招Java笔试卷深度解析:核心考点与解题思路 百度2020校招Java研发工程师笔试卷第二批这份素材在很多技术社群里被反复翻出来讨论我觉得不奇怪。作为经历过那个招聘季的人回头看这份卷子它考的不只是知识点本身更是在筛选“有没有真正写过代码、有没有踩过坑、遇到问题能不能想明白”的候选人。Java基础、集合源码、并发、JVM、网络协议这些老八股一个不少但真正决定你能不能进面试的往往是你如何在这些题里体现出自己的思考深度。这篇文章我不打算对着原卷逐题念答案而是把这份试卷拆开讲清楚它背后的命题逻辑、核心考点的解题思路以及我在实际答题过程中踩过的坑、总结出的方法。无论你是准备校招还是想系统梳理Java知识体系这篇内容都值得认真看一遍。1. 试卷整体观感与出题思路复盘1.1 题量与题型一场典型的互联网大厂综合笔试百度2020校招Java研发工程师笔试卷第二批整体题量和题型结构和当时主流互联网公司的校招笔试基本一致主要由三块构成选择题含单选和多选、编程题、问答题或简答题。选择题覆盖Java基础、集合框架、并发编程、JVM、Spring、数据库、计算机网络、操作系统等编程题通常有两道左右一道偏重算法和数据结构另一道可能结合场景设计问答题更侧重项目经验和实际问题分析能力。这种结构的特点很鲜明——考察范围宽、深度中等偏上但重点突出。实际作答时间通常为90到120分钟题量大约在30到40道选择题加上两道编程题。说实话时间是很紧张的选择题平均每道只有两到三分钟编程题每道留给你的思考时间也不会超过十五分钟。我当时做完最大的感受是这套卷子并不是要你每道题都完全答对而是看你如何分配时间和精力是否能在有限时间内拿下大概率能拿的分。1.2 难度梯度与命题策略明显在筛选“综合能力”从题目难度分布来看这份试卷呈现明显的梯度设计。基础题大概占40%主要考察语法细节、常用API、Java内存模型基础概念这些题只要系统复习过都不会丢分中等题约占40%会考察源码阅读能力、并发控制的实际应用、JVM调优基础最后20%是拉分题往往结合框架源码、线上问题排查场景、算法优化等需要候选人具备真实项目经验或深入自学的积累。出题策略上有一个明显的倾向用看似简单的题干包装复杂的问题。比如集合类的题目不会直接问你HashMap和Hashtable的区别而是给一个并发场景让你选适合的数据结构问JVM也不会直接问你堆和栈的区别而是给出一个内存溢出场景让你分析可能的OOM类型和排查思路。这种出题方式在2020年已经很成熟延用至今基本成了大厂Java笔试的通用风格。如果你只会背面经而不理解原理遇到这类题干很容易踩进陷阱。2. 核心考点拆解Java集合、并发与JVM三大基石2.1 集合框架源码级考点HashMap是永远的主角Java集合类在百度这套笔试卷里出现的频率相当高而围绕HashMap出的题几乎能单独撑起一个小章节。从考试内容来看考察点集中在几个方面HashMap的底层数据结构演进数组链表→数组链表红黑树、put和get的完整流程、扩容机制与阈值计算、哈希冲突解决方式、以及HashMap在并发环境下的问题。我对HashMap的备考建议是不要只背结论要自己画一遍put的流程图。从计算hash、定位桶下标、遍历链表/红黑树、判断重复key、到插入节点、判断是否需要树化、检查容量是否达到阈值并触发扩容每一步都要能讲清楚为什么这样设计。比如为什么要用高低位异或来扰动hashCode因为直接使用hashCode的低位参与运算在数据量小、分布不均时很容易产生碰撞而扰动函数能综合高位信息降低碰撞概率。这类细节才是真正能体现你源码功底的地方。另一个常考的点是ConcurrentHashMap。在并发场景下它是HashMap的替代方案JDK 1.7采用分段锁JDK 1.8改为CAS synchronized锁头节点。笔试经常考的是ConcurrentHashMap为什么并发性能好synchronized锁在JDK 1.8之后做了什么优化put时如何保证原子性读操作需要加锁吗这些问题的核心在于理解CAS失败重试、自旋等待、锁粒度控制等原理。我的经验是回答这类题时一定要结合源码中的具体方法比如putVal函数来讲哪怕只是口述关键行都能明显提升答案的可信度。2.2 并发编程考点从synchronized到AQS你至少要掌握到这一层并发部分在百度Java笔试题中占比通常不低考的方向很有代表性线程的创建方式、生命周期状态转换、synchronized的锁优化、volatile的可见性与有序性、wait/sleep区别、线程池参数与拒绝策略、以及AQS的基本原理。关于线程池这块几乎每年都考。核心参数corePoolSize、maximumPoolSize、keepAliveTime、workQueue、threadFactory、handler的含义要能准确说出来同时还要理解线程池的执行流程提交任务后先判断核心线程是否已满不满则创建新线程执行满了则放入队列等待队列也满了再判断是否达到最大线程数未达到则创建非核心线程如果都满了就执行拒绝策略。笔试常见题是给你一个具体参数组合问线程池中会如何执行某个任务或者Active线程数是多少。这类题需要你熟记流程又需要你结合队列类型有界或无界综合分析。volatile也是高频考点而且经常结合JMM一起考。volatile能保证可见性和有序性但不能保证原子性。笔试很容易出这样的判断题volatile能否保证i操作的线程安全性答案当然是不能因为i在字节码层面是三条指令。但如果题干把i换成对volatile变量的简单赋值那就又不一样了。这类题的陷阱就在于很多人只记住了“volatile不保证原子性”这句结论却忽略了它在特定场景下的适用性。我建议复习时用“重排序”“内存屏障”“Lock前缀指令”三个关键词把volatile完整串一遍这样无论怎么考都能接住。2.3 JVM考点内存区域、GC与类加载三板斧JVM在百度笔试里的地位可以说和并发平起平坐。考察范围集中在几块运行时内存区域划分、对象创建过程、GC算法与垃圾收集器、类加载机制与双亲委派、JVM调优工具使用。运行时数据区域的题相对基础但很多人在“方法区/元空间到底是什么”上会翻车。JDK 1.8之前方法区是实现称为永久代JDK 1.8之后永久代被移除改为元空间使用本地内存。笔试常考的是字符串常量池原来在永久代Java 7之后移到了堆中这对OOM的触发位置有什么影响这类题说到底是考你内存区域的边界和变更历史是否清楚。GC方面需要重点掌握的是Minor GC、Major GC、Full GC之间的区别以及新生代Eden From Survivor To Survivor和老年代的分配规则。另外CMS和G1的优缺点对比也是热门考点尤其注意G1的Region布局与可预测停顿时间模型。很多资料喜欢直接列一堆GC参数让背但我更建议你理解每个参数背后的目标——比如-Xmx设置堆最大值、-XX:MaxGCPauseMillis设置G1目标停顿时间这些参数都是用来解决特定问题的理解了应用场景记忆自然牢固。类加载机制也是必考项。双亲委派模型的流程要能画出来类加载请求先由子加载器委托给父加载器只有当父加载器无法完成加载时子加载器才尝试自己加载。这道题往往会和“能否自己写一个java.lang.String类并加载成功”结合来考答案是不能原因正是双亲委派机制会保证核心类库的String被Bootstrap ClassLoader加载。这种题看着简单实际上考察的是你对沙箱安全机制的理解深度。3. 编程题实战从思路到代码的完整拆解3.1 高频题型一链表与二叉树的操作百度笔试的编程题很少出那种纯背模板的题目更多是考察你在约束条件下写干净代码的能力。链表反转、链表环检测、二叉树层序遍历、最近公共祖先这类题出现的频率极高。比如链表反转要求你写迭代法和递归法两种实现面试官会关注你对指针交换过程的掌握程度而非简单背结论。一个让我印象深刻的题目是给定一个二叉树返回其节点值自底向上的层序遍历即按从叶子层到根节点层逐层遍历。这道题表面上就是层序遍历的变体但很多人写的时候会在“自底向上”这个要求上卡壳。正确做法是先做正常的自顶向下层序遍历最后把结果列表reverse一下时间复杂度O(n)空间复杂度O(n)。这个题目考察的不是你能否记住BFS模板而是你是否能意识到“逆向输出”本质上只是对结果做一次翻转。实际写代码时可以用LinkedList的addFirst方法也可以最后使用Collections.reverse两种方式都能通过。再举一个动态规划的题目。有一类笔试常考题是“最长回文子串”或“编辑距离”这类题如果没系统练过DP很容易在状态转移方程那里卡住。我建议所有准备校招的同学都要熟练掌握一套动态规划的思考框架确定base case → 定义dp数组含义 → 推导状态转移方程 → 确定遍历顺序 → 举例验证。以最长回文子串为例dp[i][j]表示从i到j的子串是否为回文转移方程是dp[i][j] (s.charAt(i) s.charAt(j)) (j - i 3 || dp[i1][j-1])。注意边界条件j - i 3时长度为1或2或3只要两端相等就一定是回文不需要考虑内部。这种细节处理好了代码就不容易出bug。3.2 场景设计题不只是写算法还要考虑实际约束百度笔试中有一类题很有意思——它不会直接给你一个LeetCode原题而是结合业务场景描述一个问题要求你设计解决方案。比如求一个大文件中的Top K频率词或者设计一个含过期时间的本地缓存。这类题考的是工程思维。以Top K频率词为例如果文件特别大不能一次性加载到内存就需要使用分治策略把大文件拆分成小文件每个文件分别统计词频再归并结果或者使用外部排序结合小顶堆维护一个大小为K的小顶堆遍历词频哈希表当堆中元素不足K个时直接入堆否则与新元素比较如果新元素频率大于堆顶则替换。关键点在于你要能解释清楚为什么用小顶堆而不是大顶堆——因为我们需要筛出频率最高的K个堆顶应该是最小值方便淘汰。系统设计类题目在笔试阶段多为初步方案面试才展开详谈但在笔试中把方案画清楚、关键组件说明白会大大提升你的综合评分。我当时答题的原则是先列出核心数据结构再写伪代码或关键函数最后补充复杂度分析和优化思路。这套答题框架让我在编程题上几乎没失过分。3.3 手动演练一道经典笔试题的完整作答为了让你看得更直观我挑一道典型的百度风格笔试编程题完整走一遍从审题到提交的手写过程。题目给定两个字符串text和pattern实现一个函数判断text中是否存在pattern的排列即包含相同字符但顺序可以不同的子串。若存在返回起始下标不存在返回-1。这个题目一看就是用滑动窗口。思路是先统计pattern中每个字符的频率然后维护一个长度为pattern.length()的窗口在text上滑动每次判断窗口内字符频率与pattern的频率是否匹配。如果用数组计数每次滑动需要更新窗口进入和离开的字符并维护一个match变量记录已经匹配的字符种类数。完整代码如下public static int findAnagramStart(String text, String pattern) { if (text null || pattern null || text.length() pattern.length()) { return -1; } int[] target new int[256]; for (char c : pattern.toCharArray()) { target[c]; } int[] window new int[256]; int left 0, right 0; int match 0; // 记录当前窗口中已满足频率相等的字符种类数 int required 0; // pattern中不同字符的种类数 for (int i 0; i 256; i) { if (target[i] 0) { required; } } while (right text.length()) { char in text.charAt(right); window[in]; if (window[in] target[in]) { match; } right; while (right - left pattern.length()) { if (match required) { return left; } char out text.charAt(left); if (window[out] target[out]) { match--; } window[out]--; left; } } return -1; }这道题完整考察了滑动窗口、数组计数、双指针三个核心技巧。我在笔试时写这种题会先注释清楚思路再写核心逻辑最后把边界情况如text为null、pattern为空、长度不足放在开头判断有效避免遗漏也能让阅卷人一眼看到你的严谨性。4. 计算机网络与数据库容易被忽视的送分区域4.1 TCP与HTTP三次握手、四次挥手如何答出差异化Java笔试中计算机网络的占比不算大但一旦出现基本都是经典必考内容。TCP三次握手、四次挥手、TIME_WAIT状态、HTTP状态码语义、HTTPS的握手过程、HTTP/1.1与HTTP/2的区别这些都是高频考点。这些知识点本身不难问题在于大部分人回答得千篇一律很难在众多考生中脱颖而出。以TCP三次握手为例基础回答可能只说明每一步发送的报文类型SYN、SYNACK、ACK但如果能进一步解释“为什么需要三次握手”就更能体现理解深度。核心原因是三次握手可以防止历史连接的重复初始化请求突然到达服务器导致服务器错误地建立连接。具体来说如果只有两次握手客户端发送的SYN因为网络拥堵延迟到达客户端已经超时重发SYN并建立了新连接而旧SYN此时才到服务器服务器还以为这是客户端的另一个新连接请求就会为它分配资源并回复SYNACK造成资源浪费。三次握手中的第三次ACK能告诉服务器“这个连接确实是我当前想建立的”让服务器能忽略过期SYN。这种深入原理的回答才是在笔试主观题里拿高分的正确姿态。HTTP方面注意状态码的分类和典型场景200表示成功301/302表示重定向304表示未修改缓存相关400表示客户端请求错误401表示未认证403表示禁止访问404表示资源不存在500表示服务器内部错误502表示网关错误503表示服务不可用。我在复习时把这些状态码编成了场景记忆法比如登录过期返回401权限不够返回403页面找不到404后端挂了502这样比死记硬背强得多。4.2 MySQL重点考点索引失效与事务隔离级别数据库相关题目中MySQL的出现频率最高。考试重点集中在索引底层数据结构B Tree vs B Tree、最左前缀原则、索引失效场景、事务的ACID特性、隔离级别与并发问题脏读、不可重复读、幻读之间的关系、MVCC机制、以及一条SQL的执行流程。索引失效是选择题的常客。典型的失效场景包括对索引列使用了函数如WHERE YEAR(create_time) 2020、隐式类型转换如把字符串索引列和数字比较、like查询以通配符开头%abc、联合索引不满足最左前缀、使用or连接非索引列等。很多人在复习时列了各种失效场景但考试时可能会稍微变换形式比如问“在order表上user_id, create_time建立了联合索引以下哪个查询不会走索引”选项里可能包含WHERE user_id 1 OR status 2这种就需要你判断出or会直接导致索引失效。事务隔离级别也是必考。MySQL默认的隔离级别是可重复读它通过MVCC解决了快照读下的幻读问题但当前读下仍可能产生幻读需要加临键锁Next-Key Lock来避免。笔试常考的是让你判断某个隔离级别下会发生哪些并发问题或者给你一个隔离级别问能否避免某类问题。复习时要记住一个递进关系读未提交可能脏读、不可重复读、幻读→ 读已提交可能不可重复读、幻读→ 可重复读可能幻读→ 串行化全避免。这个递进不只是背下来而是要理解每一级锁的粒度变化是如何逐步解决并发问题的。5. 框架与中间件考点Spring、Redis、消息队列5.1 Spring核心机制IoC与AOP的底层实现百度笔试卷对Spring框架的考察也相当重视通常会涉及IoC容器的生命周期、Bean的作用域、循环依赖的解决方式、AOP的底层代理机制、以及Spring事务的传播行为。IoC这一块最常见的题是Spring IoC容器中Bean的实例化顺序是怎样的这涉及BeanDefinition的解析、BeanFactoryPostProcessor的执行、BeanPostProcessor的注册、以及Aware接口的回调。简单记忆可以总结成一个生命周期实例化 → 属性填充 → Aware回调 → BeanPostProcessor前置处理 → 初始化方法init-method / PostConstruct→ BeanPostProcessor后置处理 → 使用 → 销毁。面试官可能不会直接考这个顺序但如果你能在谈到“Spring如何管理Bean”时自然地带出这条链路会显得功底扎实。循环依赖的解决是另外一个高频考点。Spring默认使用三级缓存来解决单例Bean的属性循环依赖singletonObjects一级缓存存放完整单例、earlySingletonObjects二级缓存存放半成品单例、singletonFactories三级缓存存放对象工厂。考题常问的是“为什么需要三级缓存二级缓存直接存对象不行吗”答案是为了处理AOP代理的创建时机——Spring希望在对象实例化之后、属性填充之前就能生成代理对象让注入的依赖是代理后的对象。如果没有三级缓存AOP代理的介入时机就很难处理得优雅。这类题需要你提前阅读过相关源码否则靠猜很难答到点子上。5.2 Redis与消息队列一致性与高可用方案Redis在校招笔试里出镜率越来越高考点包括数据类型底层的实现结构、持久化机制RDB/AOF比较、缓存穿透/击穿/雪崩的解决方案、分布式锁的实现方式、以及高可用的哨兵和Cluster架构。缓存一致性是各类考试和面试的高频场景题。典型的题干是更新数据库数据和删除缓存时应该先删缓存还是先更新数据库如果操作失败怎么保证最终一致业界常见的方案是Cache Aside Pattern旁路缓存模式即读的时候先读缓存读不到再读数据库并回填缓存写的时候先更新数据库再删除缓存。这个策略最大的优势在于即使删除缓存失败也不会出现大面积数据不一致顶多造成一次缓存未命中的开销。但如何避免并发场景下先更新数据库后删缓存导致的脏读可以引入延迟双删或者通过订阅数据库Binlog异步更新缓存。笔试时不需要你给出线上成熟方案但必须能对比几种方案的优劣体现出场景化思考。消息队列相关考点以概念和应用为主消息队列的作用异步、削峰、解耦、消息可靠投递的流程生产端到Broker到消费端的确认机制、消息重复消费与幂等性设计、消息顺序性的保证方式。有些笔试会要求你设计一个消息队列的消费幂等场景比如消费端收到重复消息时如何处理。最直接的方式是使用业务唯一ID做去重表或借助Redis的SETNX命令标记已处理消息。这个考点虽然简单但能反映候选人是否有分布式系统设计意识。6. 实战复盘答题时间分配与避坑指南6.1 典型失分点汇总这些坑你也可能踩结合我自己和周围同学的做题经验百度笔试中最常见失分点集中在以下类型。第一Java基础选择题里关于字符串的“”和equals的区分。new String(abc)和abc是否相等这涉及字符串常量池的概念。如果你不清楚字面量赋值会复用常量池对象而new一定会创建新对象这道送分题也可能答错。我的经验是遇到字符串相关题目永远先画一个内存图标出常量池和堆中的对象再判断引用是否指向同一个对象。第二并发编程里synchronized锁的是谁。下面的代码锁对象到底是什么public synchronized void method() {} public static synchronized void method() {}前者锁的是当前实例this后者锁的是当前类Class对象。这个考点非常简单但确实有很多人会混淆。笔试里还有一种变形题synchronized(obj)锁的是obj如果两个线程锁的对象不是同一个那么锁就不会互斥。这题的关键是识别出锁的粒度而不是死记结论。第三多线程选择题中关于sleep和wait的对比。很多人把两者搞混虽然它们都能让出CPU但sleep不会释放锁会抛出InterruptedExceptionwait会释放锁等待notify/notifyAll唤醒。如果能记住“sleep属于Thread类wait属于Object类”这个底层差异很多衍生题也能迎刃而解。6.2 我的答题策略先做会做的再啃硬骨头百度的笔试时间有限我在考场上的答题顺序是这样的发卷后先把所有题目快速浏览一遍把最确定的题标记出来优先做选择题中遇到不确定的先排除明显错误的选项再结合知识储备进行判断编程题先写思路注释再补代码即使时间不够也要把思路写清楚因为笔试系统往往会对代码进行人工或者半自动评分思路清晰得分的前提。对于编程题我还有一个建议先保证时间复杂度正确再优化常数因子。比如要求O(n)复杂度的题你在笔试环境中写出一个O(n log n)的解法就算能跑过测试用例也可能会被扣分。相反思路对但少数用例超时通常比思路错误要好得多。所以写题前一定要分析清楚题目给出的数据范围再确定算法选择。另一个重要的策略是不要在一道选择题上耗太久。一道题如果超过三分钟还没把握先标记跳过等全部完成后再回头思考。我在模拟笔试时经常发现那些卡住的选择题回头再看时因为大脑已经切换到其他知识模块反而更容易从新的角度找到突破口。6.3 时间不够用这几种题型建议果断放弃如果笔试时间过半还剩大量题目没有完成你就要学会做取舍。根据我的经验以下几种题目可以暂时跳过优先确保其他题目的正确率。一是涉及非常偏门API的题目。比如让你判断某个Java NIO.2中新增的Files类方法的返回值或者某个Spring注解的底层实现细节如果你不常用临时回忆大概率也回忆不准不如放弃。二是题干特别长的场景选择题。这类题通常需要仔细阅读业务描述但在时间紧张的情况下你可以先读问题部分和选项部分然后带着问题倒推题干往往能大幅节省时间。三是需要大量计算的题目。比如给定JVM参数计算对象在内存中的占用大小或给定GC日志判断某次GC的类型。这类题计算费时且容易出错如果时间不足建议先跳过把它们放在最后处理。当然跳过不等于乱蒙。即使不确定也要结合常识选一个相对最靠谱的选项因为笔试成绩可能算总分也可能按比例折算多对一道题就能多一分进面试的几率。6.4 考前一周的高效复习路径如果你正在备考百度这类大厂校招最后一周建议这样安排前两天集中做真题或模拟题且一定按真实考试的时间来约束自己提前熟悉节奏中间三天按模块查漏补缺重点复习HashMap、并发、JVM、MySQL索引、Spring生命周期、Redis缓存这几个核心板块最后两天温习错题把高频知识点过一遍同时动手写几道经典编程题练手感。复习资料方面我不推荐零散地刷大量博客最好以一份成体系的笔记或教材为主线遇到不懂的知识点再定向搜索。这比东看一眼西看一眼要高效得多。如果你时间充裕可以自行整理一份“百题速查表”按知识点、常考题型、易错点三列来组织考前翻一遍非常有帮助。我还想特别提醒编程题千万要动手写不能在脑子里过一遍就当自己会了。手写能帮你发现很多问题比如边界条件考虑不全、API记错、循环终止条件写错等。多做几道绝对不吃亏。我在备考时给自己定了规矩每天至少手写两到三道中等以上难度的算法题一直坚持到考前效果相当明显。7. 从笔试到面试这份试卷暴露出的能力模型7.1 为什么大厂偏爱“理解原理”而不是“背诵结论”从这份试卷的风格来看百度对候选人的核心期待是“理解原理”而非“背诵结论”。一道选择题可能只看你知不知道某个结论但一道问答题或编程题会逼你把结论背后的原理讲清楚。如果你只记住了“HashMap线程不安全”但说不清楚为什么线程不安全、具体在哪个环节可能出问题、以及如何解决那这道题你大概率得不了高分。我建议所有备考的人都做一次“追问训练”每学一个知识点不断问自己“为什么这样设计”“如果不这样做会怎样”“这种方案的代价是什么”。比如学习跳表时问自己为什么Redis要用跳表而不是红黑树实现有序集合从实现难度、范围查询效率、并发控制等角度对比分析就能得出自己的答案。这种追问式学习会让你面对大厂笔试的场景化题目时游刃有余。7.2 如何用一份笔试成绩为后续面试铺路笔试并不仅仅是一个淘汰机制它在后续面试中也有参考价值。有些面试官会调出你的笔试答卷直接追问“这道题你当时是怎么想的”。这时候你如果在笔试时留下了清晰、有逻辑的答题痕迹面试就有了一个很好的切入点。所以笔试作答时的策略性非常重要。选择题看不出来但编程题和问答题质量基本能反映你代码风格和思考深度建议代码变量命名规范、注释到位、逻辑分块清晰。即使最终没有进入面试这份笔试经验本身也是很有价值的学习材料它能帮你找到自己知识体系中的薄弱环节针对性补齐。7.3 持续沉淀从校招笔试到企业级Java开发最后想说的是百度2020校招Java研发工程师笔试卷第二批虽然已经是过去几年的题目但它考察的知识框架到今天依然适用。Java基础、集合源码、并发编程、JVM、数据库、框架与中间件这些依然是Java研发岗位的必修课。差距在于你是否能把这些知识点用“场景”连接起来形成自己的技术判断力。这种能力不是考前突击就能立刻获得的需要平时多写代码、多阅读源码、多复盘线上问题。校招只是职业生涯的起点笔试更像是一次系统性的知识体检。如果你把备考当成一次深度学习的机会而不是单纯为了通过考试那么无论这份试卷结果如何你的收获都会远超预期。我个人的体会是真正拉开竞争力的并不是记住了多少知识点而是你遇到复杂问题时能否快速定位核心矛盾、设计合理方案、并用干净可靠的代码落地。这份试卷正是在测试这一点。希望这篇文章能帮你把知识体系再夯实一层也祝你在求职路上少踩坑、多拿offer。
返回列表