针对校招的同学,如何确定面试标准?应该面试哪些内容?对实战能力的考察应该占多少比重?对算法的考察应该考察到什么程度?这些问题对常年只做社招的同学是比较模糊的,往往遇到面试的时候无题可问,或者问完不知道怎么对结果打分。这里总结了一下针对一个大厂工程开发团队,大概应该有的一些面试标准,和一些常用题。
常用标准
- 学习能力强&快: 既然是校招而不是社招,证明我们是希望招一些比较有潜力的候选人进行培养,所以学习能力就很重要,我们希望他能在未来扛大旗,他需要学习的东西就很多,掌握快速学习能力的同学无疑是我们最需要的。如何考察学习能力是比较难的,因为我们不可能让他现在去学习,然后过段时间来看他的成果,做一我们可以迂回一下,出一些实时计算题,可以是算法,或者数据结构等,需要短时间内理解题目并转换思维去解题,这样能考察他的一个思维敏捷性和快速获取信息的能力,侧面反映他的学习理解能力。
- 技术基础扎实: 这个比较简单,针对算法、数据结构、计算机基础等校内基础课程,由浅入深问即可。
- 实战能力必须考核: 不管是校招还是社招,实战能力都是必须考核的一项,我们不能招进来一些只会死记硬背面试题,照本宣科回答问题的候选人,我们希望的是招进来一两个月就能独立进行基础开发。尤其是现在网上各种面试宝典盛行,只要有心,常见面试问题基本都可以找到答案,这个地方有人会想,那我针对问题深入去问不就行了吗?这个地方就要解释一下了,针对校招同学,其实一些问题的深度我们是不能像社招的高级研发工程师的标准去问,我们更多的考察是学习能力和技术基础,所以一些企业开发生态的问题他们比较缺乏经验,这样并不能体现出他们的实际开发能力。这个问题其实也比较简单,一道好的笔试题能体现候选人的代码水平,证明他的能力是否是一个只有理论的空中楼阁。
- 岗位不同,算法由浅及深: 算法能体现候选人的思维敏捷能力和基础知识的掌握程度,针对校招的同学,是必须考的,但是各个岗位不一样,考核的内容可以由浅及深,大概有这个一个顺序:业务开发岗->架构开发岗->数据开发岗->算法开发岗。一般前两个问到排列、简单动态规划差不多了,后两个可以有一些场景题、非常规思维题。
校招面试题
编程基础
- 解释 && 与 || 的短路原则
- switch 中 case 后不写break 会怎么样
在 switch 语句中,如果 case 分支后不写 break,会触发 “穿透(fall-through)” 现象:程序会继续执行下一个 case(或 default)分支的代码,而不会检查下一个 case 的条件是否匹配,直到遇到 break 或 switch 语句结束。
- while 与 do–while的区别
while 和 do-while 都是编程语言中用于循环执行代码块的控制语句,但它们在执行逻辑和适用场景上有明显区别,核心差异在于循环条件的判断时机。
while 循环:先判断条件,再决定是否执行循环体。
do-while 循环:先执行一次循环体,再判断条件决定是否继续。
java
- 解释final 对象不可变与变量不可变,final形容类表示什么,final形容方法表示什么
修饰对象 | 含义 | 核心特点 |
---|---|---|
变量 | 引用不可变 | 基本类型值不变,引用类型地址不变(内容可改) |
类 | 类不可继承 | 防止子类扩展或修改类的行为 |
方法 | 方法不可重写 | 保证方法逻辑的稳定性,不被子类篡改 |
- java 遍历集合时删除其中元素的方法(for 与 iterator的使用区别)
直接for循环删会报错,使用iterator不会,因为其实他是copy了一个副本出来做修改。
- java是值传递还是引用传递
在 Java 中,所有参数传递都是值传递(pass-by-value),不存在引用传递(pass-by-reference)。这是 Java 语言设计的明确特性,但其表现形式可能会因参数类型(基本类型 vs 引用类型)不同而产生混淆。
当传递基本类型(如int、char、boolean等)时,方法接收的是该值的副本。在方法内部修改这个副本,不会影响原变量的值。
当传递引用类型(如对象、数组、字符串等)时,方法接收的是对象引用地址的副本(而非对象本身)。此时:
若在方法内部修改对象的属性,会影响原对象(因为副本和原引用指向同一个对象);
若在方法内部将副本指向新对象,不会影响原引用(因为只是修改了副本的地址)。
- 继承与接口的区别
- 什么是重载,什么是重写,java是如何实现重载与重写的
- 什么叫多态,什么是动态绑定,java是如何实现多态与动态绑定的,与之对应的还有静态绑定,方法表,这些是什么
在继承中,this.getClass()获取的是子类class还是父类class
在继承关系中,this.getClass() 始终返回当前对象实际所属的子类的 Class 对象,而不是父类的 Class 对象。
这是因为 this 指向的是当前正在运行的对象实例,而 getClass() 方法的语义是 “返回对象运行时的实际类型”(即动态类型),而非声明时的类型(静态类型)。
- 对象是如何实现判等的
在 Java 中,对象的 “判等”(判断两个对象是否相等)需要根据具体场景区分两种语义:引用相等和内容相等,分别通过 == 运算符和 equals() 方法实现。
- 解释java中的泛型
使用类型做参数
- 反射的理解
反向获取类的属性&方法
- java的动态代理是什么,有什么实例
jdk和cglib
- java的Exception与error的区别,常见的Exception都有哪些
exception可处理,error不可处理,会导致应用程序终止
- 常用的集合类型都有哪些?
Collection(List、Set、Queue)、Map
- HashMap是如何实现的?它与ConrrentHashMap有什么区别?使用方式与使用场景下分别有什么不同?
- java 中 深拷贝与浅拷贝的区别,如何实现深拷贝
- 什么是LRU,什么是LFU?如何通过LinkedHashMap来实现LRU与LFU?
LRU(最近最少使用):选择最近最久未使用的数据予以淘汰。
LFU(最不经常使用算法):选择最近使用次数最少的数据予以淘汰。
参考:通过LinkedHashMap来实现LRU与LFU
多线程
- 线程与进程有什么区别?
- 线程有哪些状态?
- 什么是守护线程?守护线程创建的线程是不是守护线程?普通线程创建守护线程,普通线程退出后守护线程会不会退出?
- thread,runable与callable有什么区别?
- 如何中断线程?线程如何检测是否被中断?线程被中断后会立即停止执行么?
- await,notify,notifyAll的使用场景?
- 什么是可重入锁?
- synchronized与reentrantLock的区别,以及分别使用场景与实现原理?
- volatile的作用以及原理什么?它是线程安全的么?
保证内存可见性、禁止指令重排序,内存屏障、总线嗅探机制,不安全
- ThreadLocal的实现原理?
给当前线程一个map对象,线程私有。
- 为什么要使用线程池?常用的线程池工厂类有哪些?
- 如何设计一个线程池?以及需要关注那些重要的指标?
- 为什么会有线程安全的问题?常用来解决线程安全的方式有哪些?
- 用线程安全的类来组合设计的类也是线程安全的吗?
- 多线程中如何避免死锁?
JVM虚拟机
- java为什么会有虚拟机?
跨平台+内存管理回收
- 什么是堆内存?什么是栈内存?java对象在内存中的哪块区域进行分配?
大部分是堆内存中分配、部分会再栈、部分会在常量池(方法区)
- 栈内存是什么时候分配的?
线程调度到某个方法
- 为什么会出现OOM?OOM的主要原因是什么?
内存溢出、内存泄露
- 描述一下GC。哪些对象需要GC?什么时候GC?采用什么样的方式进行GC?
YoungGC、FullGC,无引用对象会被GC,内存超出阈值,垃圾回收算法:复制、标记清除、标记整理。垃圾回收器:CMS、G1
- java内存区域是如何划分的?
堆、虚拟机栈、方法区、本地方法栈、程序计数器、直接内存、元空间
- 什么是双亲委派模式?如果自己实现一个java.lang.String类,会不会被加载?
优先父类加载器加载,防止同一个类重复加载。不会
基本设计模式
- 如何理解设计模式?常用的设计模式都有哪些?
单例、工厂、代理、适配器、建造者、观察者
- 单例模式中,两种实现分别是什么?懒加载会有什么问题?如何解决?
懒汉模式+饿汉模式,懒汉式在多线程环境下会导致多个实例被创建,破坏单例特性。可以使用双重检查锁解决。
数据结构与算法
- 数组与链表的区别?各自优劣点是什么?
数组方便修改某一个位置的数据,链表需要便利找到某个位置。
链表插入某一个数据很容易,修改前后指针就行。数组是定长的,超过长度不能增加数据,不超长的情况想要插入需要挪动后面的所有数据往后移。
- 如何用java设计一张图?
- 定义Vertex类存储顶点数据,Edge类存储边的关系(起点、终点、权重)。
- 选择邻接表(推荐)或邻接矩阵存储顶点与边的关联。
- 实现基础操作(添加顶点 / 边、获取邻接顶点)。
- 根据需求扩展遍历(DFS/BFS)、最短路径(Dijkstra 算法)等功能。
- 如何理解广度优先与深度优先?
- 常用排序算法,简述其算法过程
冒泡、快速、插入、堆、统计排序、基数排序
- 利用快速排序的思路求D(K): 求一堆数字中第n大(小)的数字,利用快排思想
快速排序冒泡排序的进化版,第一个数据把做全量对比,把比这个数小的放到它左边,大的放到右边,然后分别对左右两部分再进行快排,递归计算完成排序。也是分治法的使用,但只求第n大,那只需要递归其中一部分就好了,其他部分不用完全排好序也能求出第n大。
- 什么是内排序,什么是外排序? 什么是稳定排序,什么是不稳定排序?
内排序:所有待排序的数据都能一次性加载到内存中进行排序的算法。常见内排序算法:冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序、希尔排序等
外排序:待排序的数据量过大,无法一次性加载到内存中,必须借助外部存储(如磁盘、磁带) 分阶段进行排序的算法。
稳定排序:在排序过程中,对于值相等的元素,其在原始序列中的相对顺序会被保留。常见稳定排序算法:冒泡排序、插入排序、归并排序、基数排序等
不稳定排序:排序过程中,值相等的元素可能会改变原始相对顺序。常见不稳定排序算法:选择排序、快速排序、堆排序、希尔排序等。
- 常用的查找算法,各自优缺点以及其使用场景?
算法 | 定义 | 时间复杂度(平均) | 前提条件 | 核心优点 | 核心缺点 | 典型场景 |
---|---|---|---|---|---|---|
顺序查找 | 从数据集合的起始位置开始,逐个元素与目标值比较,直到找到目标或遍历完所有元素 | O(n) | 无(支持任何结构) | 简单、通用 | 效率低 | 小数据、链表、无序数据 |
二分查找 | 针对有序数据集合,每次通过比较中间元素与目标值,将查找范围缩小一半(左半或右半),重复直到找到目标或范围为空 | O(log₂n) | 有序、随机访问 | 高效(大数据) | 依赖有序,维护成本高 | 有序静态数组、大数据快速查找 |
插值查找 | 二分查找的改进版,针对均匀分布的有序数据,通过公式估算目标值的位置(而非固定取中间值),公式为:mid = low + (target - arr[low]) * (high - low) / (arr[high] - arr[low]) | O(log log n) | 有序、随机访问、均匀分布 | 均匀分布下效率更高 | 对分布敏感 | 均匀分布的有序数据 |
哈希查找 | 通过哈希函数将目标值映射到数据存储的位置(哈希地址),直接访问该位置查找目标。核心依赖哈希表(Hash Table)数据结构 | O(1) | 哈希表结构 | 极快的单值查找 | 冲突处理复杂,不支持范围查找 | 字典、缓存、动态数据 |
二叉查找树 | 一种有序二叉树,左子树所有节点值小于根节点,右子树所有节点值大于根节点。查找时,通过与根节点比较,递归进入左 / 右子树 | O(log₂n) | 二叉树结构,需维护有序性 | 兼顾动态维护与有序性 | 可能退化,需平衡优化 | 动态有序数据、范围查找 |
分块查找 | 结合顺序查找与二分查找的思想,将数据分为若干块,块内无序但块间有序。先通过块索引(有序)确定目标所在块(二分或顺序),再在块内顺序查找 | O(√n) | 分块有序,块内无序 | 平衡效率与动态性 | 实现复杂,需额外索引 | 动态大数据、分块存储 |
数据库
- 数据库索引如何理解?mysql中索引的实现原理是什么?
- 什么是联合索引?a、b两个列都有索引或者a\b是联合索引,用where条件 a > b 会走索引吗?
- 数据库中事务指的是什么?其ACID指的是什么?
- 数据库语句分析explain详细说明
- sql中where 与 having的区别?
spring
- spring基本原理,什么是依赖注入,什么是截面?
- 截面AOP的实现原理?
web
- 常用的web开发框架
- cookie和session 的区别
Cookie:轻量、存储在客户端、适合非敏感数据,受大小限制,安全性较低。
Session:存储在服务器、适合敏感数据,无大小限制,安全性高,但会消耗服务器资源。