背景
本人WHU软工,大三,之前用Java刷过一些题目,寒假跟着敲了苍穹外卖。两个星期前开始背八股,看了点java基础,JVM,反射,多线程,还有SSM框架,MySQL,Redis。本来觉得3月底才能做好面试的准备,没想到3月11号被约第二天面试,觉得时间太紧想拖到15号,但tx那边说再晚简历就释放了,于是没办法硬着头皮约了13号。
开局
本来提前十分钟进面试了,设备也调试好了,手贱把窗口关了,再进去设备显示有问题,摄像头和麦克风打不开,此时面试官已经在了,最后花了几分钟解决(小插曲,问题不大)。
首先是简短的自我介绍,面试官注意到我简历上写的两个项目都是后端的工作,问我后端具体做哪些工作,我说了些文档编写、接口设计、代码编写之类的。随后面试官问我在Java之前用的是C++还是C(很可惜我都不会),我说原来上课学了C++,可是不了解,后来大二学了Java决定把它作为主要语言,但直到最近才决定深入学习Java。
然后面试官就说,先出道代码考核题看看你的代码基础。WTF??上来就算法是我没想到的。
算法
题目比较常规,非递归先序遍历二叉树。大概二十分钟写出来了。
这里贴一种参考解法:
public static void preorderTraversal(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
System.out.print(node.val + " ");
// 因为栈是后进先出的,所以我们先把右孩子压入栈
if (node.right != null) {
stack.push(node.right);
}
// 然后把左孩子压入栈
if (node.left != null) {
stack.push(node.left);
}
}
}
面试官让我自己构造一棵树进行测试。其实十分钟基本逻辑已经出来了,但中途一直报Error:Class, Interface, or Enum expected.后来面试官提示我,方法要写到Main类里面。。直接尬住了。好在还算平稳度过这关。
结束算法之后,面试官说之前忘记提了,他们做的是手Q方面的业务,主要是安卓端的开发,而我投的是后台方向,问我是否感兴趣。我:当然感兴趣啊!(能有得去就行..)
Java基础
问:Java里的内存管理机制和垃圾回收机制?
答:先从JVM说起,宏观上分为四部分——类加载器、运行时方法区(此处口误了,应该是运行时数据区)、执行引擎、本地方法库。运行时方法区(同上,口误)又分为几个部分。线程私有的部包括程序计数器、虚拟机栈、本地方法栈,线程共享的部分是堆和方法区。答的过程中顺便讲了一下每个部分自己所了解的内容(譬如程序计数器线程私有的原因,是要保证多线程环境下,线程切换时能记住某线程上次执行到的位置)。垃圾回收机制讲了Minor GC和Full GC,还有内存分配策略(新生代、老年代),但答的时候一直把老年代说成永久代,复盘时才发现(小问题,小问题)。本来还想答垃圾回收算法,一紧张给忘了,写在补充里面了。
补充:
Minor GC 和 Full GC的区别?
Minor GC:回收新生代,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快。
Full GC:回收老年代和新生代,老年代的对象存活时间长,因此 Full GC 很少执行,执行速度会比 Minor GC 慢很多。
垃圾回收算法有哪些?
垃圾回收算法有四种,分别是标记清除法、标记整理法、复制算法、分类收集算法。
- 标记清除算法
首先利用可达性去遍历内存,把存活对象和垃圾对象进行标记。标记结束后统一将所有标记的对象回收掉。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。
- 复制清除算法
半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。
特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。
- 标记整理算法
根据老年代的特点提出的一种标记算法,标记过程仍然与 标记-清除 算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。
- 分类收集算法
根据各个年代的特点采用最适当的收集算法。一般将堆分为新生代和老年代。新生代使用复制算法,老年代使用标记清除算法或者标记整理算法。
在新生代中,每次垃圾收集时都有大批对象死去,只有少量存活,使用复制算法比较合适,只需要付出少量存活对象的复制成本就可以完成收集。老年代对象存活率高,适合使用标记-清理或者标记-整理算法进行垃圾回收。
问:线程同步有哪些方式?
答:答了Synchronized和ReentrantLock两点(复盘才发现,我一直把Synchronized读成Synchronous了,检讨一秒)。答的时候侧重答了它们的不同点,一是ReentrantLock需要主动调用(lock( )和unlock( )方法),二是Synchronized只有非公平锁,ReentrantLock既可以设置公平锁也可以设置非公平锁(顺便答了一下公平锁的定义,但有点模糊了,等会补充)。后来想起来Volatile没说,不过问题不大。
补充:
公平锁和非公平锁有什么区别?
- 公平锁 : 锁被释放之后,先申请的线程先得到锁。性能较差一些,因为公平锁为了保证时间上的绝对顺序,上下文切换更频繁。
- 非公平锁:锁被释放之后,后申请的线程可能会先获取到锁,是随机或者按照其他优先级排序的。性能更好,但可能会导致某些线程永远无法获取到锁。
ReentrantLock和synchronized区别?
1. 使用synchronized关键字实现同步,线程执行完同步代码块会自动释放锁,而ReentrantLock需要手动释放锁。
2. synchronized是非公平锁,ReentrantLock可以设置为公平锁。
3. ReentrantLock上等待获取锁的线程是可中断的,线程可以放弃等待锁。而synchonized会无限期等待下去。
4. ReentrantLock 可以设置超时获取锁。在指定的截止时间之前获取锁,如果截止时间到了还没有获取到锁,则返回。
5. ReentrantLock 的 tryLock() 方法可以尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够获取则返回true,否则返回false。
volatile 关键字的两个作用:
1. 保证了不同线程对共享变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2. 禁止进行指令重排序。
之后面试官问我有没有过多线程开发的经历,我说没有,但打算这学期做一个类似12306或者演唱会抢票机制那样的东西,到时候可以学习一下。
计算机网络
问:TCP和UDP的区别?
答:说了TCP的面向连接(必须一对一连接)、可靠性(超时重传机制),还提到了二者应用场景的不同(如基于SMTP协议发邮件时,应用TCP,观看视频直播应用UDP),又引出了UDP传输较快(准确的说法是传输效率较高),节省资源。其实还有好几点没答,还得练。
补充:
TCP和UDP的区别?
1. TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接。
2. TCP提供可靠的服务;UDP不保证可靠交付。
3. TCP面向字节流,把数据看成一连串无结构的字节流;UDP是面向报文的。
4. TCP有拥塞控制;UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如实时视频会议等)。
5. 每一条TCP连接只能是点到点的;UDP支持一对一、一对多、多对一和多对多的通信方式。
6. TCP首部开销20字节;UDP的首部开销小,只有8个字节。
问:TCP连接过程?
答:手到擒来了吧,哥们?三次握手四次挥手框框一顿整,这里就不再详细列出作答过程了。
不得不说计网问的确实基础。
排序算法
首先问我项目中是否运用过排序算法,我回答直接调用Collections.sort( )或者Array.sort( )。于是引出了第一个问题:
问:sort( )的原理是什么?
答:首先明确底层用的是快速排序。然后简单答了一下快排的逻辑,选一个数作基准,基准两侧递归排序,等等。然后说了快排的时间复杂度是O(NlogN),嘴贱说了空间复杂度是O(1),其实应该是最坏O(N),平均O(logN)。
问:还有哪些O(NlogN)的排序算法?
答:答了二分排序和堆排序。本来以为二分很清晰,没想到自己脑子乱了,答得不好,最后想了半天说是基于二分查找的,自己编了一个二分排序算法,先确定有序区,然后对无序区的每个元素逐个在有序区内进行二分查找,决定插入位置,貌似逻辑也成立,糊弄过去了。其实O(NlogN)还有归并排序和希尔排序,但当时没想到。
补充:
附一张排序算法总结图,来源:JavaGuide/docs/cs-basics/algorithms/10-classical-sorting-algorithms.md at main · Snailclimb/JavaGuide (github.com)
最后一问竟然是?!
没想到最后居然问回了Java,还这么简单:
问:抽象类和接口的区别?
答:答了三点:一是抽象类的子类不可以多继承,但一个类可以实现多个接口(这里答得不好,答得更像类和接口的区别),二是抽象类里可以有抽象方法和非抽象方法,接口里只能有抽象方法,三是接口里的变量默认被public static final修饰,也可以理解为常量。
问:二者设计理念有何不同?
答:抽象类是在结构上的考量,比如鸟作为抽象类,猫头鹰、鹦鹉继承它,是它的子类;而接口则是针对行为,比如猫头鹰、鹦鹉都可以实现飞行这个接口。不知道答得对不对。
补充:
抽象类与接口的区别:
1、语法层面上的区别
- 抽象类可以有方法实现,而接口的方法中只能是抽象方法;
- 抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型;
- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2、设计层面上的区别
- 抽象层次不同。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口只是对类行为进行抽象。继承抽象类是一种"是不是"的关系,而接口实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是具备不具备的关系,比如鸟是否能飞。
- 继承抽象类的是具有相似特点的类,而实现接口的却可以不同的类。
反问
问:我是第一次面试,比较紧张,请您客观地评价一下我的表现,还有什么可以提升的地方?
答:在我这边看来,你不像是第一次(我:我确实是第一次!),感觉你准备比较充分,对基础的理解相较于你这个阶段比较突出,代码考核也比较符合预期,整体上蛮不错的。
问:请问您这个部门具体涉及到哪些业务?
答:手Q(好像中间确实提到过),主要进行搜索、群、频道等等功能模块的开发,主要使用Java或者Kotlin语言,还有一些创新性的项目,涉及面比较广,可能要自己写前端、后端(简言之,全栈),技术栈也比较丰富。文章来源:https://www.toymoban.com/news/detail-853133.html
总结
人生第一次面试,感觉良好,面试官非常nice,一小时以内就被约复试了。题目确实很简单很基础,但自己答得还有很多欠缺的地方,继续努力吧。文章来源地址https://www.toymoban.com/news/detail-853133.html
到了这里,关于腾讯客户端Java一面的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!