360春招那场笔试,我到现在还记得第一屏客观题弹出来时的压迫感:PHP基础、Web安全、数据库、网络协议,什么都在考,而且选择题的量比想象中大得多。很多人拿到“客观题合集”这五个字,以为刷一遍语法题就够了,真上了考场才发现,360的客观题考的不是“会不会”,而是“熟不熟”——同样的知识点,换一个问法,换一组干扰项,就是一道新题。
这篇文章我不打算给你整理一份“360真题答案表”,那东西网上到处都是,背了也没用。我想做的是另一件事:把2018春招这套笔试客观题背后的考察逻辑拆开,看看360作为一家以安全为核心的技术公司,在PHP开发工程师这个岗位上到底想筛选什么样的人。如果你正准备投PHP开发岗,或者已经在刷题阶段,这篇文章可以帮你把复习方向从“背题”扭转到“理解命题人意图”上来。
1. 360笔试客观题的考察范围与出题逻辑
1.1 客观题在整场笔试中的定位:不是送分题,是筛选器
很多人对客观题有误解,觉得选择题、判断题就是基础题,是“热热身”用的。但在360这种体量的公司,技术岗笔试的客观题恰恰是淘汰率最高的环节之一。原因很简单:投递量太大了,简历筛选之后必须有一轮低成本、高覆盖度的初筛,客观题就是干这个用的。
它考察的维度很直接:你对PHP这门语言的理解有没有形成体系?你的知识面是停留在能跑通业务代码,还是真的下功夫抠过语言底层和边界情况?你的安全意识是挂在嘴上,还是刻在处理输入输出的每一个习惯里?
我做完这套题之后最大的感受是,360的客观题不是从《PHP程序员面试题大全》里随机抽的,而是有明确的出题倾向:
- 基础语法题占大头,但不会直接问你“echo和print的区别”,而是把变量引用、作用域、运算符优先级这些细节揉进一个具体场景里;
- Web安全相关考点密集出现,毕竟公司的安全基因摆在那里;
- 数据库和常见框架的题目会结合工程实际,不是单纯背概念;
- 有一些题目看起来超纲,比如让你判断某个伪协议的作用,或者某个序列化魔术方法的触发时机,其实是故意的——就看你平时有没有主动拓宽过技术视野。
1.2 从热搜词反推考点分布:大家在搜什么,往往就是考什么
我当时复习的时候习惯刷技术社区里的热搜词,发现一个特别有意思的现象:笔试考完那几天,“php错误处理”、“php伪协议”、“php序列化”、“PDO访问封装”、“ThinkPHP3.2.3”这些词的热度会明显上升。这其实暴露了大多数人的两个痛点:一是复习时根本没把这些点当重点,二是考完才发现这些才是拉开分差的地方。
结合2018年春招那套题的实际情况,我把考点分布整理成了一张表,你可以对照着检查自己的盲区:
| 考点类别 | 典型考察内容 | 2018春招出现频率 | 复习优先级 |
|---|---|---|---|
| PHP基础语法 | 变量引用、作用域、数组函数、字符串函数 | 高 | 必须掌握 |
| 面向对象 | 魔术方法、访问控制、静态成员、接口与抽象类 | 高 | 必须掌握 |
| 错误与异常 | error_reporting级别、异常捕获机制、错误抑制 | 中高 | 必须掌握 |
| Web安全 | 文件包含、反序列化、SQL注入、XSS | 高 | 360特色,重点准备 |
| 数据库 | PDO预处理、SQL语句、事务、索引基础 | 中高 | 必须掌握 |
| 框架知识 | ThinkPHP生命周期、路由、I函数过滤 | 中 | 视岗位要求准备 |
| 网络与Linux | TCP/IP基础、HTTP协议、常用命令、进程 | 中 | 不可忽略 |
| 算法与逻辑 | 简单数组操作、字符串处理、时间复杂度判断 | 中 | 基础即可 |
这张表里的后四类,恰恰是很多“只刷语法题”的候选人翻车的地方。尤其是安全相关考点,普通公司可能只考一道SQL注入判断,360会从文件包含、伪协议、反序列化、上传校验多个角度反复出题,而且干扰项设置得非常细,稍微有点模糊记忆就会选错。
2. PHP基础考点里的高频陷阱:从热搜词反推命题人偏好
2.1 运算符优先级与结合性:送分题变成送命题的重灾区
PHP的基础语法题,按理说应该是客观题里最友善的一部分。但我在复盘时发现,只要题目涉及运算符优先级,错误率就会明显上升。原因不是大家不知道表,而是实际做题时很少有人会刻意去背整张优先级表,遇到某道题想当然地按“从左到右”算,结果就掉坑里了。
举个经典例子,下面这段代码输出什么:
$a = 0; $b = 5; if ($a || $b = 10) { echo $b; }很多人一看$a || $b = 10,下意识会想:||两边是逻辑或,$b = 10是赋值不是比较,赋值的优先级比||低,所以实际上相当于($a || $b) = 10,然后直接懵了。
正确的理解是:PHP中赋值运算符=的优先级低于||,所以表达式实际上是$a || ($b = 10)。由于$a是0(假),继续判断右侧$b = 10,这个赋值表达式的值是10(真),所以整个条件为真,$b被赋值为10,最终输出10。
我当时做题时在草稿纸上写了“赋值优先级在逻辑或之后”这个结论,后来回看,这类题的核心就是两件事:第一,背清楚=、==、===、&&、||、??这组运算符的优先级关系;第二,养成用括号消除歧义的习惯。考试时看到运算符混杂的表达式,先别急着算,把优先级层级标出来再动手。
还有一个与之相似的陷阱:&&和||的短路求值。比如:
$a = true; $b = 0; $result = $a || ($b = 5); echo $b;因为$a为true,短路导致$b = 5根本不执行,所以$b仍然是0。这个点几乎年年有公司考,360当年也出了类似的变体,只不过把条件换成了函数调用。
2.2 错误处理与异常机制:你以为的“报错”其实是一套完整体系
“php错误处理”能上热搜,说明这个点在笔试里卡住了不少人。PHP的错误处理跟Java、Python很不一样,它不是单纯的try-catch一套机制走天下,而是分为传统错误级别、异常、错误处理器几个层次。
客观题里最常见的是考error_reporting()、display_errors、log_errors这三个配置的关系,以及@错误抑制符的行为。比如题目会问:生产环境下应该怎么配置?
正确答案思路是:display_errors设置为Off,避免错误信息直接暴露给用户;log_errors设置为On,把错误写入日志;error_reporting设置为E_ALL,尽量暴露所有问题。听起来很简单,但干扰项会故意设置成“display_errors设为Off后所有错误都不会被记录”,这种说法一看就是错的,但很多人选的时候又犹豫了,原因就是没把“显示错误”和“记录错误”这两个动作分离清楚。
另一个高频点是把@抑制符和set_error_handler()结合出题。有个选择题大概是这样的:如果自定义了一个错误处理函数,那么被@修饰的表达式触发的错误还会不会进入这个函数?
答案是:会。@只能控制错误是否被显示和记录,但不能阻止错误被传送到自定义错误处理函数。这套题当年很多人选错,因为大家对@的认知停留在“让错误不显示”的层面,没有深入理解它和错误处理流程的关系。
再往后延伸一点,PHP 7之后的Throwable接口、Error和Exception的区别,也是偏爱考的点。Error是程序本身的问题(比如类型错误、参数错误),Exception是程序运行中可以被捕获的异常。在PHP 7之前,很多致命错误是没法被catch的,PHP 7之后Error类让大部分致命错误也能被捕获了。这个演进过程如果理解了,做这类题就不需要死记硬背。
2.3 数组与字符串函数:零散知识点背后的体系化整理方式
数组函数和字符串函数是PHP客观题的题海区域,因为函数实在太多了,出题人随手就能挑一个考你返回值、参数顺序或者边界行为。我自己复习的时候走过一段弯路:一个函数一个函数地背手册,背到后面全混了。
后来我换了一种方法——按“函数家族”来整理,效果立竿见影。举个例子:
- 检查数组中是否存在某个key,可以用
array_key_exists()、isset()、empty(),但它们的语义完全不同。isset()在值存在且不为null时返回true,array_key_exists()只要key存在就返回true(哪怕值是null),empty()则是值存在、非null、非空字符串、非0等“空值”才返回true。 - 字符串查找,
strpos()如果找到了目标会返回位置(整数),找不到会返回false。但位置可能从0开始,很多人在判断时直接写if (strpos($str, $needle)),当目标恰好位于字符串开头时,strpos返回0,0被当作false,于是判断失败。这个坑客观题里出现了不止一次,而且选项设计很狡猾,会同时出现“返回0”、“返回false”、“返回null”三个看上去都对的说法。
把这些函数放在一起对比记忆后,你会发现它们的差异点和命题角度其实很集中:要么考返回值类型(是整数、字符串还是布尔值),要么考边界条件(位置0、空字符串、null值),要么考参数顺序(needle和haystack谁在前面)。摸清这三个维度之后,再遇到没见过的函数,也能按这个思路去推断它的行为。
3. 安全类客观题:360笔试里最有辨识度的部分
3.1 PHP伪协议:一道题暴露你平时看不看CTF
“php伪协议”这个热搜词,明显就是从笔试和CTF题里带出来的。伪协议在日常业务开发里用得不多,但在文件包含、文件读取相关漏洞里是出镜率极高的概念,360作为安全公司,在这一块出题几乎是必然的。
客观题通常不会让你现场构造利用链,而是考你对不同伪协议的理解:
php://filter:常用于读取文件源码,配合read=convert.base64-encode可以把文件内容以base64编码输出。这个概念在CTF题目中经常出现,也是考察频率最高的一个。php://input:可以读取POST原始请求体,在有allow_url_include开启的旧配置下可能触发代码执行。data://:可以把数据流封装为文件流,同样需要allow_url_include配合。file://:直接访问本地文件系统,属于最基础的文件协议。
当年那道题的具体问法我不记得原样了,但考察方向是:在给定的几个伪协议中,哪些可能被用来读取文件内容,哪些可能被用来执行代码。选项里会故意混入http://、ftp://这些看起来和网络相关的协议,让你犹豫。
我的复习建议是:把每个伪协议的功能、触发条件、常见配合(比如php://filter的base64_encode)、需要开启的PHP配置项,做成一张对照表。笔试考的是概念,面试如果问到安全问题,下一步就会追问“你对文件包含漏洞了解多少”,这时候如果你能把include $_GET['file']这种代码为什么危险讲清楚,比背多少道选择题都有用。
3.2 反序列化与对象注入:概念题其实考的是触发时机
“php序列化中文”这个热搜词看起来很偏门,但它背后对应的是序列化与反序列化这个重要考点。序列化就是把对象或者数组转换成一个可存储、可传输的字符串,反序列化就是把这个字符串还原成对象或数组。
客观题对序列化的考查通常有两条线:
一条是基础线:serialize()和unserialize()的行为、序列化字符串的格式(比如O:4:"User":1:{...}这样的结构,O代表对象,4是类名长度,User是类名,1是属性数量)。题目可能会给你一个数组,问你序列化后的字符串是什么结构,或者反过来,给你一段序列化字符串,问你还原后是什么类型。
另一条是安全线:对象注入。核心是unserialize()在还原对象时会触发一些魔术方法,比如__wakeup()、__destruct()、__toString()等。如果反序列化的数据是用户可控的,攻击者就可以构造恶意的序列化字符串,让程序在反序列化时执行危险操作。客观题一般考的是:哪个魔术方法会在反序列化时被调用?__wakeup的触发顺序是进入unserialize时,而__destruct是在对象被销毁时,两者时间点完全不同。知道这个区别,就能判断题目里描述的执行顺序对不对。
我在准备这一块的时候,把常见的魔术方法触发时机写在了手册空白处,反复看了好几遍:
__construct:对象创建时__destruct:对象销毁时__wakeup:反序列化恢复对象时__sleep:序列化时__toString:对象被当作字符串使用时__call:调用不存在的方法时
需要特别注意的一点是,安全线的题目本质上考察的是“攻击者如何控制输入”,但对开发工程师来说,更应该记住的是防御姿势:永远不要对用户提交的数据直接调用unserialize(),如果要支持,也要加白名单校验、HMAC签名,或者用allowed_classes参数限制类白名单。这套防御思路比背考点更有实际价值。
3.3 文件操作与上传校验:客观题里的场景化安全判断
除了伪协议和反序列化,360的客观题还特别喜欢把“文件上传”场景化来考:给出一段PHP代码,让你判断它存在什么安全问题。这种题看起来是在考代码阅读,实际上是在考你对文件上传校验链路完整性的理解。
经典的一个判断点是:只看扩展名白名单够不够?
不够。攻击者可以结合.htaccess、.user.ini、上传目录下的解析漏洞等方式绕过扩展名校验。所以客观题里如果出现“只要扩展名对就安全”的说法,这一项一定是错误项。
另一个判断点是:move_uploaded_file()函数的参数顺序。正确用法是move_uploaded_file($tmpName, $destPath),目标路径应该由你根据上传类型重新生成,而不是直接使用用户传来的文件名。如果代码把$_FILES['file']['name']直接拼接到目标路径上,就可能出现路径覆盖、目录穿越等问题。
还有一类题会考include和include_once、require和require_once的区别。很多人觉得这四个没区别,但客观题会精确考“如果文件不存在或引入失败,各自会有什么后果”:include产生警告,脚本继续执行;require产生致命错误,脚本停止执行;带_once后缀的会先检查文件是否已被引入,避免重复加载。这个考点单独看很简单,但放到文件包含漏洞的语境里就有了新层次——不同的引入方式在错误处理上的差异,会影响整个程序的健壮性。
4. 数据库与框架相关的客观题:工程能力的分水岭
4.1 PDO与预处理:为什么这一题几乎必考
“php数据库pdo访问封装类下载”能成为热搜词,说明很多人在笔试前临时抱佛脚,想找一个现成的PDO封装拿去背。但客观题不会因为你背了一个封装类就让你过关,它考的是你对PDO机制本身的理解。
PDO、mysqli、mysql(老扩展)这三者的区别是历年常客。
mysql扩展已在PHP 7中移除,不再讨论;mysqli是面向MySQL的专用扩展,支持面向对象和面向过程两种风格;PDO是PHP Data Objects的缩写,提供统一的数据库访问接口,支持MySQL、PostgreSQL、SQLite等多种数据库。
客观题最爱考的点是PDO预处理到底为什么能防SQL注入。这里要理解到位:预处理是把SQL模板先发送给数据库进行预编译,用户输入只作为参数值传入,数据库引擎不会把参数值当作SQL指令解析,因此即使参数里包含' OR '1'='1,它也只是被当作字符串字面值处理。
但是要注意一个坑:PDO是否使用预处理取决于你是否真的用了预处理方法。如果只是用PDO::query()拼接字符串,那跟普通mysql_query没有任何区别,照样存在注入风险。所以看到选项里写“只要用了PDO就绝对安全”,可以直接排除。
另一类PDO相关题目考的是属性设置,比如PDO::ATTR_ERRMODE、PDO::ATTR_DEFAULT_FETCH_MODE、PDO::ATTR_EMULATE_PREPARES。其中ATTR_EMULATE_PREPARES决定了是否使用本地模拟预处理。如果设为false,PDO会使用MySQL原生的预处理;如果为true(默认在某些驱动下),PDO会在本地模拟,实际执行时可能把预处理退化成立即拼接。这个点对判断“某段代码是否存在注入”很重要,但客观题通常只会让你区分“预处理”和“模拟预处理”的概念,能说出差异就够用了。
4.2 ThinkPHP 3.2.3与框架生命周期:老框架为什么还在考
热搜词里出现了“thinkphp3.2.3 { fast & simple oop php framework }”,这不是乱码,是ThinkPHP框架的官方宣传语。360在2018年那会儿的老项目里,PHP技术栈用ThinkPHP的比例不低,所以笔试出框架题是合理的。
框架类客观题一般集中在两个方向:
第一个方向是框架生命周期。一次HTTP请求进入ThinkPHP后,大致会经历:入口文件加载框架基础类库 → 注册自动加载 → 解析路由 → 实例化控制器 → 调用操作方法 → 渲染模板输出响应。题目可能会混入“中间件”、“事件机制”等现代框架才有的概念当干扰项,如果对ThinkPHP3.2.3的架构不太熟,就很容易被带偏。
第二个方向是I函数和安全过滤。ThinkPHP3.2.3提供了I()方法来统一获取输入参数,并且支持在第二个参数中声明过滤方式。当时的I()方法在默认情况下会进行一些安全过滤,但并不是万能的。客观题里会把I()、$_GET直接使用、htmlspecialchars过滤等行为放在一起,让你判断各种写法是否安全。
我的建议是:备考时不用把ThinkPHP源代码全部啃一遍,但至少要知道它的请求处理主链路、I函数的实现思路、以及路由解析的基本流程。因为从这些题目能看出,公司期望PHP工程师不是只会写个控制器,而是遇到框架行为异常时,能往下追踪到入口和路由那一层去排查问题。
4.3 队列与基础中间件概念:考察知识面的广度
热搜词里还有“php队列”、“php mqtt”、“php视频会议”这些词。虽然这些不一定直接出现在客观题里,但360的笔试确实会在网络和系统基础部分夹杂一些“偏工程架构”的判断题,比如:
- 消息队列在系统中起到什么作用?(解耦、削峰、异步处理,这三个词是核心)
- Redis实现队列时,
LPUSH+BRPOP组合与LPUSH+RPOP组合有什么区别?(阻塞读与主动读的区别) - MQTT协议最典型的应用场景是什么?(物联网消息传输,轻量级发布/订阅模型)
这些题不会深挖,但如果你从来没有接触过队列、消息中间件的概念,看到题目会完全不知道在说什么。我当时在这个部分能拿分,纯粹是因为在项目里用过Redis队列,知道基本的命令语义。所以建议那些只做过CRUD的同学,在准备笔试时一定要抽出时间把消息队列、缓存、HTTP协议状态码、TCP三次握手这类基础概念过一遍,它们不一定每天用,但知识面不能让它在选择题里成为盲区。
5. 易错题答题思路复盘:一道题的完整推理过程
5.1 引用与值传递:变量机制的底层理解
有一类题几乎每场PHP笔试都会出现,就是考变量赋值后另一个变量是否会改变。比如:
$a = 1; $b = $a; $b = 2; echo $a; // 输出什么?答案是1,因为$b = $a在PHP中默认是“写时复制”的值拷贝,两者互不影响。但如果改成:
$a = 1; $b = &$a; $b = 2; echo $a; // 输出什么?答案是2,因为&建立了引用关系,$b和$a实际上指向同一个变量容器。
这类题的推理关键就一句话:搞清楚赋值时是“复制”还是“建立引用”。在此基础上,360还喜欢把它和函数传参结合:
function test(&$x) { $x++; } $a = 1; test($a); echo $a;答案是2,因为函数参数声明为引用传递,函数内修改会影响外部变量。如果去掉&,函数内只是修改了副本,外面仍然输出1。看似平淡无奇,但干扰项会把“函数参数默认是引用传递”写进选项里诱导你。记住:PHP函数参数默认是值传递,要用&显式声明才是引用传递。
5.2 静态变量与作用域:闭包和static的组合考法
另一个常见陷阱是静态变量。看这段:
function counter() { static $count = 0; $count++; return $count; } echo counter() . counter();答案是“12”,因为静态变量在函数第一次执行时初始化,之后保留上一次结束时的值,不会每次进入都置为0。这个知识点本身不难,但命题人如果把它和闭包放在一起,难度就上来了。
比如:
function makeCounter() { static $count = 0; return function() use (&$count) { return ++$count; }; } $c1 = makeCounter(); $c1(); $c2 = makeCounter(); echo $c2();这里要分清楚:静态变量$count是函数级的,makeCounter()每次调用都不会重置它,而是保留上一次的值;闭包通过use (&$count)引用它。所以$c1()把$count变成1后,$c2()会发现$count仍然是那个静态变量,值已经从0变成1,再自增后输出2。
这类题考核的核心其实是对变量作用域和生命周期的理解:静态变量活在函数存续的整个进程里,而不是某次调用里。答题时把这个大原则抓住,不管题目怎么变,都能套进去。
5.3 答题节奏与蒙题策略:客观题同样需要时间管理
2018年春招这套客观题,我记得页面上的总题量不小,单选、多选、判断混在一起。多选是最坑的:少选、错选都不得分,所以必须对每一个选项都做出确定性判断才敢勾选。
我当时的策略是分三轮:
第一轮,快速做掉有把握的题,尤其是判断和单选,每条控制在30秒内。遇到需要计算或推演的题,先在草稿纸上标记题号,不做停留。这一轮的目标是把基础分稳稳拿到手。
第二轮,回到标记的题,集中推演。对拿不准的多选题,我的做法是先判断哪些选项肯定是错的,把它们排除后,剩下的宁可少选也不要选错。因为多选题的计分规则往往是“错选零分、少选得部分分”,不确定的选项不勾,至少能保住一部分分数。
第三轮,检查一遍选项是否勾错位,尤其是题干问“以下哪项不正确”这类反向提问。我问过几个当年一起笔试的同学,都出现过反向题看漏“不”字然后选反的情况。
做题时还有一个容易被忽视的细节:题目里可能隐藏着“PHP版本限定”。同一段代码在PHP 5和PHP 7里的行为可能不一样,比如某些函数从PHP 7开始返回类型变了,或者从PHP 8开始参数做了调整。360的笔试虽然不会刻意去考版本边界,但遇到和数组、字符串处理相关的题,稍微留意一下版本背景可以避免一些误判。如果题目没有明确给版本,默认按主流稳定版本(2018年就按PHP 7.x)来推理。
6. 客观题之外的准备:从题目反推360对工程师的要求
6.1 笔试分数与项目经验的匹配逻辑:过了笔试只是起点
我在准备这场笔试时踩过一个认知误区:以为客观题全对就能进面试。实际上,客观题在整条招聘链路里的作用,更像是一个“门槛检查”,过了门槛之后,面试官真正看重的还是项目经验和解决实际问题的能力。
2018年春招的流程大概是:简历 → 在线笔试 → 面试(通常两到三轮技术面+HR面)。笔试成绩主要决定你有没有资格进面试,但面试聊什么,基本跟客观题没什么关系——面试官会问你最近做的项目、技术难点、遇到线上故障怎么排查、对某个安全漏洞的理解。
所以如果你还在校招阶段,我的建议是:客观题复习要趁早,但不要把大量时间耗在刷题上。客观题覆盖的知识点,正好可以作为项目深度思考的引子——比如你在项目里用了PDO,那你有没有想过预处理为什么能防注入?有没有踩过模拟预处理相关的坑?这些问题才是面试时能让你脱颖而出的素材。
6.2 从刷题到工程认知:安全直觉是360最看重的能力
如果要用一个词总结360这套客观题的核心气质,我觉得是“安全直觉”。这不是说所有题都和安全有关,而是它的出题角度会让你养成一种习惯:看到一个输入点,先想它会不会被恶意利用;看到一段文件操作代码,先想路径是否可控;看到反序列化,先想数据来源是否可信。
这种直觉不是背题能背出来的,而是靠平时写代码时的自我训练。我后来在项目里养成一个习惯:每个对外接口上线前,都会拿“如果是攻击者,我会怎么打”这个问题过一遍代码。这听起来像安全工程师干的事,但对PHP开发工程师来说,这种意识恰恰是360这类公司最看重的。
所以如果你现在正在准备类似的笔试,我给你的建议是:不要只刷题,把刷到的每个考点都带回项目里检验一遍。看到伪协议相关题目,去查查自己的项目里有没有include用户输入的路径;看到反序列化相关题目,检查一下有没有对用户提交的数据直接调用unserialize();看到PDO相关题目,确认一下项目里的SQL是不是都走了预处理。这样复习下来,笔试和面试其实是同步准备的。
6.3 一个额外的提醒:客观题背后的PHP版本意识
写到最后,我想特别提一下PHP版本意识。2018年的时候PHP 7已经是主流,但很多老项目还在跑PHP 5.x。笔试题目如果拿不准,可以看看它考的是PHP 5特有行为还是PHP 7新特性。比如PHP 7里foreach不再直接修改内部数组指针、增加了标量类型声明和返回值类型声明、引入了??空合并运算符,这些都有可能变成客观题的“隐藏背景”。
到了现在,PHP 8已经普及,新项目里到处都是构造器属性提升、联合类型、match表达式、命名参数这些特性。如果你是现在准备面试,除了传统基础知识点外,最好也把PHP 8的几个核心语法更新过一遍,不然面试官问“你平时用的PHP版本和它有什么明显变化”时会很被动。笔试客观题考的是过去的基础,但面试考察的是你现在能不能跟上语言的发展节奏。
我把这套题复盘完,最大的体会是:360的客观题,每一道都长着“基础题”的脸,但骨子里都在问你——你对这门语言的理解,是停留在“能用”,还是深入到“懂它为什么会这样”。把这个标准想清楚了,你的复习方式会完全不一样。