荣耀⼀⾯
荣耀 Java ⾯试
荣耀泡了好久,这⼏天终于开奖了!
不少同学看到开奖后的薪资还是⽐较满意的,给的不算低。
我从⽹上爆料的信息,整理了荣耀 25 届「通⽤开发岗」的校招薪资:
29k x 12 + 10w (年终奖)=44.8w ,同学 bg 未知,base 北京
28k x 12 + 8w (年终奖) = 41.6w ,同学 bg 硕⼠ 985 ,base 北京
27k x 12 + 10w (年终奖)= 42.4w ,同学 bg 硕⼠ 985 ,base 西安
27k x 12 + 6w (年终奖)= 38.4w ,同学 bg 硕⼠ 985 ,base 南京
26k x 12 + 8w (年终奖)= 37.2ww ,同学 bg 硕⼠ 985 ,base 上海
24k x 12 + 6w (年终奖)= 34.8w ,同学 bg 硕⼠海⻳,base 南京
22k x (14 〜16 )= 30w 〜35w ,同学 bg 本科 985 ,base 深圳
21k x (14 〜16 )= 29w 〜33w ,同学 bg 硕⼠211 ,base 西安
20k x (14 〜16 )= 28w 〜32w ,同学 bg 本科 985 ,base 深圳如果按照 offer 档次划分 的话,⼤概情况如下表格(PS :下⾯档次区分是我⾃⼰划分 的,并不⼀定完全准 确,仅供参考)

整体来看,荣耀的薪资还是不错的,跟互联⽹⼤⼚薪资⽔平差 不多。
如果在南京拿到 35w 年薪 offer ,那就是真的⾹,等同于⼆线城市拿⼀线城市的薪资了,相⽐在⼀
线城市⽣活,除去⽇常开销,可存下来的钱会更多。
那话说回来,荣耀的⾯试难度如何?
其实荣耀⾯试跟华为差不多,毕竟华为跟荣耀曾经是⺟品牌跟⼦品牌的关系,虽然现在两家公司
都是独⽴运营,但是⾯试⻛格还是相似的。
荣耀的校招⾯试流程:笔试-> ⼀⾯-> 测评-> ⼆⾯-> 进⼊录⽤状态。
⾯试共有两轮,⼀⾯会问技术⼋股多⼀些,但是问的不会特别多,⼀场⾯试⼤概是 10 个左右的技
术问题,
。⼆⾯的话,基本就是聊天局,聊学校和个⼈的经历,偶尔可能会问⼏个技术问题。
这次,跟⼤家分享今 年荣耀通⽤开发岗位的校招⾯经,这是⼀⾯,主要以技术⼋股拷打为主

荣耀⼀⾯
Java 和C 语⾔的区别是什么 ?
⾸先,Java 是⼀种⾯向对象的语⾔,强调通过对象来组织 代码和数据,重点在于对事物的建
模,关注“是什么 ”和“如何互动”,通过继承、多态等机制实现代码复⽤和扩展性,⽀持封装、继
承和多态等⾯向对象的特性。C是⼀⻔⾯向过程的语⾔,代码的结构主要是通过功能模块(函
数)来组织 的,程序的执⾏是通过调⽤这些函数来实现的,重点在于对过程的描述,即如何完
成某个任务。
其次对于不 同的平台来说,Java 只需要⼀次编译,就可以在不同的平台上⾯运⾏,对于c来说,
如果在window 上⾯编译⽣成的⽂件只能在window 上运⾏,如果想要在Linux 系统下运⾏,需要
重新在Linux 下⾯进⾏编译,原因是由于Java 有⾃⼰的⼀套虚拟机体制,Java 编译完成之后,会
⽣成class ⽂件,然后将⽣成的⽂件移到不同的平台时,Java 虚拟机会帮助我们将class ⽂件翻译成计算机所能识别的信息,这样就可以在不同平台运⾏了。
第三从 语法结构上来说,Java 去掉了c⾥⾯⽐较重要的指针的概念,对于指针的概念就是我们可
以直接去操作计算机的物理地址 ,所以使 ⽤c的时候,我们需要经常去⾃⼰申请⼀些内存空间,
⽤完之后还需要⾃⼰⼿动释放,Java 的垃圾 回收机制较好的解决了这⼀点,我们不⽤再去关⼼
申请的内存释放释放,Java 虚拟机会帮助我们去清理⼀些我们⽤不到的空间,从⽽降低了很多
出错的可能。
Java 垃圾 回收算法有哪些?
标记-清除算法:标记-清除算法分为“标记”和“清除”两个 阶段,⾸先通过可达性分析,标记出所
有需要回收的对象,然后统⼀回收所有被标记的对象。标记-清除算法有两个 缺陷,⼀个是效率
问题,标记和清除的过程效率都不⾼,另外⼀个就是,清除结束后会造成⼤量的碎⽚空间。有
可能会造成在申请⼤块内存的时候因为没有⾜够的连续空间导致再次 GC 。
复制算法:为了 解决碎⽚空间的问题,出现了“复制算法”。复制算法的原理是,将内存分成两
块,每次 申请内存时都使⽤其中的⼀块,当内存不够时,将这⼀块内存中所有存活的复制到 另
⼀块上。然后将然后再把已使⽤的内存整个清理掉。复制算法解决了空间碎⽚的问题。但是也
带来了新的问题。因为每次 在申请内存时,都只能使⽤⼀半的内存空间。内存利⽤率严重不
⾜。
标记-整理算法:复制算法在 GC 之后存活对象较少的情况下效率⽐较⾼,但如果存活对象⽐较
多时,会执⾏较多的复制操作,效率就会下降。⽽⽼年代的对象在 GC 之后的存活率就⽐较
⾼,所以就有⼈提出了“标记-整理算法”。标记-整理算法的“标记”过程与“标记-清除算法”的标记
过程⼀致,但标记之后不会直接清理。⽽是将所有存活对象都移动到 内存的⼀端。移动结束后
直接清理掉剩余部分。
分代回收算法:分代收集是将内存划分 成了新⽣代和⽼年代。分配的依据是对象的⽣存周期,
或者说经历过的 GC 次数。对象创建时,⼀般在新⽣代申请内存,当经历⼀次 GC 之后如果对还
存活,那么对象的年龄 +1 。当年龄超过⼀定值(默认是 15 ,可以通过参数 -XX:MaxTenuringThreshold 来设定)后,如果对象还存活,那么该对象会进⼊⽼年代。Synchorized 锁的具体锁的范围?
作⽤于⾮静态⽅法,锁住的是对象实例(this ),每⼀个对象实例有⼀个锁。
public synchronized void method() {}作⽤于静态⽅法,锁住的是类的Class 对象,因为Class 的相关数据存储在永久代元空间,元空间
是全局共享的,因此静态⽅法锁相当于类的⼀个全局锁,会锁所有调⽤该⽅法的线程。
public static synchronized void method() {}
作⽤于 Lock.class ,锁住的是 Lock 的Class 对象,也是全局只有⼀个。
synchronized (Lock.class) {}作⽤于 this ,锁住的是对象实例,每⼀个对象实例有⼀个锁。
synchronized (this) {}作⽤于静态成员变量,锁住的是该静态成员变量对象,由于是静态变量,因此全局只有⼀个。
public static Object monitor = new Object();
synchronized (monitor) {}http 和https 的区别?
区别主要有以下四点:
HTTP 是超⽂本传输协议,信息是明 ⽂传输,存在安全⻛险的问题。HTTPS 则解决 HTTP 不安全
的缺陷,在 TCP 和 HTTP ⽹络层之间加⼊了 SSL/TLS 安全协议,使得报⽂能够加密传输。
HTTP 连接建⽴相对简单, TCP 三次握⼿之后便可进⾏ HTTP 的报⽂传输。⽽ HTTPS 在 TCP 三
次握⼿之后,还需进⾏ SSL/TLS 的握⼿过程,才可进⼊加密报⽂传输。
两者的默认端⼝不⼀样,HTTP 默认端⼝号是 80 ,HTTPS 默认端⼝号是 443 。
HTTPS 协议需要向 CA (证书权威机构 )申请数字证书,来保证服务器的⾝份是可信的。
http 是怎么建⽴的?
是先进⾏三次握⼿之后,http 就可以传 输请求和响 应了,然后如果要断开连接,就会进⾏四次挥
⼿。

不过 http 1.1 开始,默认的连接⽅式就是⻓连接,⼀个 tcp 连接可以进⾏多次 http 请求和响 应,
减少了握⼿和挥⼿的开销。
https⼜是怎么建⽴的?
传统的 TLS 握⼿基本都是使⽤ RSA 算法来实现密钥交换的,在将 TLS 证书部署服务端时,证书⽂
件其实就是服务端的公钥,会在 TLS 握⼿阶段传递给客⼾端,⽽服务端的私钥则⼀直留在服务
端,⼀定要确保私钥不能被窃取。
在 RSA 密钥协商算法中,客⼾端会⽣成随机密钥,并使⽤服务端的公钥加密后再传给服务端。根
据⾮对称加密算法,公钥加密的消息仅能通过私钥解密,这样服务端解密后,双⽅就得到了相同
的密钥,再⽤它加密应⽤消息。
我⽤ Wireshark ⼯具抓了⽤ RSA 密钥交换的 TLS 握⼿过程,你可以从下 ⾯看到,⼀共经历了四次
握⼿:


TLS 第⼀次握⼿
⾸先,由客⼾端向服务器发起加密通信请求,也就是 ClientHello 请求。在这⼀步,客⼾端主要向
服务器发送以下信息:
(1)客⼾端⽀持的 TLS 协议版本,如 TLS 1.2 版本。
(2)客⼾端⽣产的随机数(Client Random ),后⾯⽤于⽣成「会话秘钥」条件之⼀。
(3)客⼾端⽀持的密码套件列表,如 RSA 加密算法。
TLS 第⼆次握⼿
服务器收到客⼾端请求后,向客⼾端发出响应,也就是 SeverHello 。服务器回应的内容有如下内
容:
(1)确认 TLS 协议版本,如果浏览器不⽀持,则关闭加密通信。
(2)服务器⽣产的随机数(Server Random ),也是后⾯⽤于⽣产「会话秘钥」条件之⼀。
(3)确认的密码套件列表,如 RSA 加密算法。(4)服务器的数字证书。
TLS 第三次握⼿
客⼾端收到服务器的回应之后,⾸先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证
书的真实性。
如果证书没有问题,客⼾端会从数字证书中 取出服务器的公钥,然后使⽤它加密报⽂,向服务器
发送如下信息:
(1)⼀个随机数(pre-master key )。该随机数会被服务器公钥加密。
(2)加密通信算法改变通知,表⽰随后的信息都将⽤「会话秘钥」加密通信。
(3)客⼾端握⼿结束通知,表⽰客⼾端的握⼿阶段已经结 束。这⼀项同时把之前所有内容的发
⽣的数据做个摘要,⽤来供服务端校验。
上⾯第⼀项的随机数是整个握⼿阶段的第三个 随机数,会发给服务端,所以这个随机数客⼾端和
服务端都是⼀样的。
服务器和客⼾端有了这三个 随机数(Client Random 、Server Random 、pre-master key ),接着
就⽤双⽅协商的加密算法,各⾃⽣成本次通信的「会话秘钥」。
TLS 第四次握⼿
服务器收到客⼾端的第三个 随机数(pre-master key )之后,通过协商的加密算法,计算出本次通
信的「会话秘钥」。
然后,向客⼾端发送最后的信息:
(1)加密通信算法改变通知,表⽰随后的信息都将⽤「会话秘钥」加密通信。
(2)服务器握⼿结束通知,表⽰服务器的握⼿阶段已经结 束。这⼀项同时把之前所有内容的发
⽣的数据做个摘要,⽤来供客⼾端校验。
⾄此,整个 TLS 的握⼿阶段全部结束。接下来,客⼾端与服务器进⼊加密通信,就完全是使⽤普
通的 HTTP 协议,只不过⽤「会话秘钥」加密内容。
Redis 除了缓存外还有哪些功能?
还可以⽤ Redis 实现消息队列和分布式锁。
Redis 实现分布式锁⽅式是什么 ?
分布式锁是⽤于分布式环境下并发控制的⼀种机制,⽤于控制某个资源在同⼀时刻只能被⼀个应
⽤所使⽤。如下图所⽰:

Redis 本⾝可以被多个客⼾端共享访问,正好就是⼀个共享存储系统,可以⽤来保存分布式锁,⽽
且 Redis 的读写性能⾼,可以应对⾼并发的锁操作场景。Redis 的 SET 命令有个 NX 参数可以实现
「key 不存在才插⼊」,所以可以⽤它来实现分布式锁:
如果 key 不存在,则显⽰插⼊成功,可以⽤来表⽰加锁成功;
如果 key 存在,则会显⽰插⼊失败,可以⽤来表⽰加锁失败。
基于 Redis 节点实现分布式锁时,对于加锁操作,我们需要满⾜三个 条件。
加锁包括了读取锁变量、检查锁变量值和设置锁变量值三个 操作,但需要以原⼦操作的⽅式完
成,所以,我们使 ⽤ SET 命令带上 NX 选项来实现加锁;
锁变量需要设置过期时间,以免客⼾端拿到锁后发⽣异常,导致锁⼀直⽆法释放,所以,我们
在 SET 命令执⾏时加上 EX/PX 选项,设置其过期时间;
锁变量的值需要能区分来⾃不同客⼾端的加锁操作,以免在释放锁时,出现误释放操作,所
以,我们使 ⽤ SET 命令设置锁变量值时,每个客⼾端设置的值是⼀个唯⼀值,⽤于标识客⼾
端;
满⾜这三个 条件的分布式命令如下:
SET lock_key unique_value NX PX 10000
lock_key 就是 key 键;unique_value 是客⼾端⽣成的唯⼀的标识,区分来⾃不同客⼾端的锁操作;
NX 代表只在 lock_key 不存在时,才对 lock_key 进⾏设置操作;
PX 10000 表⽰设置 lock_key 的过期时间为 10s ,这是为了 避免客⼾端发⽣异常⽽⽆法释放锁。
⽽解锁的过程就是将 lock_key 键删除(del lock_key ),但不能乱删,要保证执⾏操作的客⼾端就
是加锁的客⼾端。所以,解锁的时候,我们要先判断锁的 unique_value 是否为加锁客⼾端,是的
话,才将 lock_key 键删除。可以看到,解锁是有两个 操作,这时就需要 Lua 脚本来 保证解锁的原⼦性,因为 Redis 在执⾏ Lua
脚本时,可以以 原⼦性的⽅式执⾏,保证了锁释放操作的原⼦性。
// 释放锁时,先比较 unique_value 是否相等,避免锁的误释放
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0end
这样⼀来,就通过使⽤ SET 命令和 Lua 脚本在 Redis 单节点上完成了分布式锁的加锁和解锁。
红⿊树和B+ 树区别?
** 磁盘I/O 次数:** 对于有 N 个叶⼦节点的 B+Tree ,其搜索复杂度为O(logdN) ,其中 d 表⽰节点允许的最⼤⼦节点个数为 d 个。在实际的应⽤当中, d 值是⼤于100 的,这样就保证了,即
使数据达到千万级别时,B+Tree 的⾼度依然维持在 3〜4 次的磁盘 I/O 操作就能查询到⽬标数
据。⽽红⿊树是⼆叉树,每个⽗节点的⼉⼦节点个数只能是 2 个,意味着其搜索复杂度为
O(logN) ,这已经⽐ B+Tree ⾼出不少,因此红⿊树检 索到⽬标数据所经历的磁盘 I/O 次数要更多。
** 数据量处理:**B+ 树适合处理⼤量数据,尤其是⽆法全部装⼊内存的情况,⽽红⿊树更适合
内存中的数据操作。
** 顺序访问:**B+ 树的叶⼦节点形成链表,使得对数据的顺序访问更为⾼效。⽽红⿊树作为⼆
叉树,顺序访问效率较低。
** 应⽤场景:**B+ 树在处理⼤量数据并频繁进⾏磁盘I/O 操作的场景下更有 优势,特别是在需要
⾼效的范围查询和顺序访问时。⽽红⿊树在内存中的数据结构和算法实现中更为常⻅,适⽤于
响应时间要求严格的场合,⽐如 hashmap 有⽤红⿊树,以及 epoll 底层也⽤了红⿊树。
