Java后端面试题汇总(部分解析)
Java后端面试题汇总
这里写自定义目录标题
Java
Java基础
-
short s1 = 1; s1 = s1 + 1;有错吗? short s1 = 1; s1 += 1; 有错吗?
-
Object 类常用方法有那些?
-
java 中是值传递引用传递?
值传递。对象类型传的是引用对象内存地址的值,也是值传递,但是可以直接修改对象。
-
构造方法能不能重写?能不能重载?
可以重载,但是不能被重写,因为构造方法是不能被继承的。
-
抽象类和接口区别?
- 抽象类可以有构造方法,接口没有
- 抽象类可以有普通成员变量,接口只有静态成员变量(public static final)
- 抽象类可以有非抽象的普通方法,接口所有方法都是抽象的(public abstract)
- 抽象类可以有静态方法,接口不能
- 类只能继承一个类,但可以实现多个接口
-
String str=”aaa”,与 String str=new String(“aaa”)一样吗?
-
那针对浮点型数据运算出现的误差的问题,你怎么解决?
使用BigDecimal计算,并使用String初始化
-
面向对象的特征有哪些方面?
-
访问修饰符 public,private,protected,以及不写(默认) 时的区别?
-
Hashcode 的作用
从HashMap角度看,JVM每new一个Object,它都会将这个Object丢到一个Hash表中去,这样的话,下次做Object的比较或者取这个对象的时候(读取过程),它会根据对象的HashCode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。若HashCode相同再去调用equal。
重写Hashcode一定要重写equals。
-
深拷贝和浅拷贝的区别是什么?
-
String 和 StringBuilder、StringBuffer 的区别?
-
接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?
接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。
-
一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
可以包含,但是只可以有一个public类
Java集合
-
ArrayList和LinkedList
-
HashMap如何排序
使用LinkedHashMap,它是HashMap的子类,可以直接被HashMap承接。
LinkedHashMap使用了双向链表,支持自定义排序,也支持插入顺序排序。
-
Vector,SynchronizedList,CopyOnWriteArrayList
SynchronizedList读写操作都会加锁
CopyOnWrite采用写时复制,写的时候通过复制一个新数组,防止阻塞读操作,读写操作在不同数组上。读读,读写不互斥,适合读多写少。占用内存较多。
-
HashMap底层实现,put()操作,resize()操作
-
ConcurrentHashMap,HashTable
-
ArrayList遍历删除元素问题
使用foreach方式删除,原理是使用迭代器,迭代器支持快速失败,一旦修改元素就会报错。
可以使用直接for(int i = 0; i < n; i++) 的方式遍历删除,但是要注意删除的时候会略过一个元素,删除时要手动i--
Java异常
-
finally中包含return语句
会返回finally中的return导致try/catch中的return无效。因为程序会先运行finally再进行try/catch的retrun。
-
Error 与 Exception 的区别
Java反射
-
动态代理
jdk动态代理和cglib动态代理。jdk动态代理的类一定要实现接口,动态代理类实现InvocationHandler接口,再实现invoke(),再调用Proxy.newProxyInstance()获得代理类即可。
jdk动态代理对象效率高,但是执行效率低,CGLib创建效率低但是执行效率高(直接修改字节码得到)。但是jdk动态代理效率越来越好,所以spring中通常使用jdk动态代理,不能使用再使用CGLib动态代理。
-
除了使用 new 创建对象之外,还可以用什么方法创建对象?
- 获得class对象,使用newInstance。ClassName.class.newInstance()
- 继承Cloneable接口,实现clone()方法
- 反序列化
-
java 反射的作用
-
反射的使用步骤
- 获取 Class 对象:Class.forName()
- 获取对象方法/属性:classObject.getMethods()/getFields()
- 调用对象方法:method.invoke()
Java线程、进程、并发
-
线程和进程的关系
-
创建线程的方法
- 继承Thread
- 继承Runnable
- 继承Callable,有返回值
-
线程池的7个参数
-
volatile的作用,线程安全单例模式实现,及其中volatile的作用
-
notify()和notifyAll()区别
-
Thread 类中的 start() 和 run() 方法有什么区别?
-
sleep()和wait()区别
- sleep()是Thread类的,阻塞但不会释放资源。
- wait()是Object类的,阻塞且释放资源。
-
sychronized和ReentrantLock
-
synchronized不可响应中断,Lock可以。
-
都为可重入锁。
-
-
锁升级
-
无锁,偏向锁,轻量级锁,重量级锁。
-
以及Markword的锁字段和hashcode信息存储。
-
-
线程池的submit()和execute()
- execute()只能提交Runnable对象,且返回void,主线程没有办法获取到异常信息。
- submit()可以提交Runnable,Callable,可以返回Future对象获取结果以及异常信息。
JVM
-
64位JVM,int为多少字节
4字节。
-
GC如何分代
-
双亲委派模型
-
垃圾收集算法,重点关注CMS和G1
CMS:增量标记
G1: 原始快照
-
JVM中的各个组成部分
堆,本地内存,虚拟机栈,本地方法栈,程序计数器。
-
垃圾收集的三种基础算法
-
JVM加载类的过程
加载、连接(验证、准备、解析)、初始化。
-
什么时候会执行Minor GC和Full GC
-
从新生代晋升到老年代的条件
- 达到新生代最大年龄(默认15)
- 大对象直接分配到老年代
- 分配担保机制:新生代装不下,进行Minor GC后仍分不下。如果打开了分配担保,若历次新生代晋升老年代对象的平均值,则允许对象尝试直接晋升,若不足则出发Full GC;否则直接先进行Full GC。
- 动态对象年龄判断:若Survivor区中相同年龄的对象的所有大小之和超过Survivor空间的一半,年龄大于或等于该年龄的对象可直接进入老年代。
数据库
MySQL
-
InnoDB和MyISAM
-
数据库三范式
- 第一范式(1st NF - 列都是不可再分)
- 第二范式(2nd NF- 每个表只描述一件事情)
- 第三范式(3rd NF- 不存在对非主键列的传递依赖)
-
InnoDB事务的四个隔离级别
-
脏读,不可重复读,幻读
-
ACID原则,如何保证
-
如何实现可重复读,解决脏读
-
MVCC如何实现
创建Read View,Read View包含四个字段:
- 创建当前事务的事务id
- 还未提交的事务id列表
- 还未提交的事务id列表中最小的事务id
- 下一个要开启的事务id(不在列表中)
-
如何解决幻读
Next-Key Lock = 间隙锁 + 行锁
-
InnoDB底层存储格式
B+树,每个节点就是一个数据页,数据页内有页目录、最小记录、数据、最大记录。页内通过二分查找页目录定位到数据所在的分组(槽),在分组内进行遍历查找(分组限制了大小,防止链表过长)。
-
B+树的数据结构,为什么不用B树。
从磁盘IO次数进行考虑。
-
B+树和红黑树和二叉平衡树(AVL树)
-
MySQL中的索引类型
按不同类型划分:
- 数据的存储方式:聚集索引、非聚集索引
- 索引包含的列数:单列索引、联合索引
- 字段特性:主键索引、唯一索引、前缀索引、普通索引
-
Hash索引和B+树索引
Hash索引不支持范围查询。
-
索引失效的场景
- 隐式类型转换
- 模糊匹配
- or的左右不都含有索引
- 函数计算(新版本支持对函数建立索引)
- 表达式计算
- 联合索引最左匹配原则
-
为什么主键索引最好是自增的
防止页分裂导致内存碎片,导致结构不紧凑影响查询效率。
-
MySQL死锁的发生和解决
发生:并发插入的时候,两方插入了间隙锁,两方请求插入意向锁。
间隙锁和间隙锁是可以重叠的,插入意向锁和间隙锁是互斥的。
-
undolog
undolog不会进行刷盘,它是记录在redolog里面的。重启后,由redolog恢复出undolog的数据再对未提交的事务进行回滚。
undolog和脏数据一起刷新到磁盘。
undolog其实也是以页的形式(和数据一样的形式)存储在Buffer Pool中,保证redolog落盘后,undolog和脏页才会落盘。
-
redolog
redolog是循环写的,若满了会阻塞MySQL,把脏页写回磁盘然后移动checkpoint。
-
binlog
binlog可用于全量恢复数据。
-
redolog的刷盘时机和binlog的刷盘时机
redolog有可能在事务执行中进行刷盘。
binlog一定是事务提交后才刷盘。
-
两阶段提交过程和原因
以binlog为主。
-
一条更新语句执行的过程
Redis
-
redis的使用场景
-
redis的原理
单线程,多路复用。
-
redis和memcached
-
redis是严格单线程吗
redis把生成快照等耗时操作交给了后台线程。
6.0后把对socket的读写也交给了后台IO线程。
-
redis的5种基本数据结构以及实现方式
-
redis持久化:AOF和RDB的优缺点及实现
-
混合持久化RDB+AOF
-
过期删除策略
分为volatile和all以及noeviction。
-
内存淘汰策略
惰性删除,定期删除。
-
缓存常见的几个问题:
- 缓存雪崩:大量缓存同时失效,设计随机过期时间,加锁防止请求大量落到数据库上。
- 缓存击穿:热点数据失效,加锁防止请求大量落到数据库;设置永不过期。
- 缓存穿透:数据库没数据,使用Bloom Filter或者设置段时间的null值。
-
如何保证缓存和数据库的一致性
先更新数据库,再删除缓存。
-
Redis支持原子性吗
不支持,但只是不支持回滚而已。
-
Redis集群
- 主从复制:读写分离。
- 哨兵(Sentinel)模式:哨兵使用Raft选举算法,选出leader进行主从节点故障转移。
- 切片(Sharding):使用16384个哈希槽。
计算机网络
-
OSI七层以及TCP/IP四层,以及没层对应的作用。
-
输入网址到网页显示,期间发生了什么
-
HTTP 1.0/1.1/1.2/1.3 每一个版本的区别以及提升
-
HTTPS的握手过程(RSA和ECDHE两种)
-
证书验证的过程,以及递归证书验证。
-
TCP三次握手、四次挥手
-
为什么需要三次握手、为什么需要四次挥手
-
四次挥手的每个状态,time-wait为什么2MSL
-
TCP流量控制
窗口关闭:客户端使用窗口探测报文;服务端使用窗口通告报文
糊涂窗口综合症:
- 客户端使用Nagle算法,避免发送小数据。
- 服务端避免通告小窗口。
-
TCP拥塞控制
- 慢启动
- 拥塞避免
- 拥塞发生
- 快速回复(快重传)
-
TCP半连接队列和全连接队列
-
Syn Flood攻击如何解决
队列无法加入的时候返回syn cookie。
-
粘包问题
- 固定长度的消息。
- 特殊字符作为边界。
- 自定义消息结构。
-
DNS
-
ARP
-
ICMP(ping使用的报文)
-
IP地址分类;无分类地址CIDR
操作系统
-
进程和线程的区别
-
进程通信的方式
-
进程有几种状态以及状态间的转换
-
死锁发生的四个必要条件
-
解决死锁的方法:
- 预防:破坏4个条件中的一个,对应用的影响最大。
- 避免:如银行家算法,尝试分配,若分配后,剩余资源可以让其他进程完成,则分配,否则不分配。
- 检测:检测系统中是否出现死锁。
- 解除:检测到死锁后,对死锁进行操作,如放弃某一进程,释放资源。
-
进程调度算法
-
SJF:短作业优先
-
FCFS:先来先服务
-
HRRN(Highest Response Ratio Next):高响应比优先
优先级 = (等待时间 + 要求服务时间)/ 要求服务时间
- 等待时间越长,优先级越高
- 等待时间相同时,要求服务时间越短,优先级越高
-
RR(Round Robin):时间片轮转
-
HPF(Highest Priority First):高优先级优先
-
Multilevel Feedback Queue:多级反馈队列
每个队列优先级不同,单独队列中为时间片轮转算法,用完时间片还没有完成,则进入下一队列
-
-
内存管理,虚拟内存
-
内存分页和内存分段的结构,页表和段表的结构
-
为什么会有多级页表
-
段页式存储
-
TLB是什么
Translation Lookaside Buffer,简称快表,其实就是页表缓存,当在页表缓存找不到时才去页表查找。
页表存储在内存中。
缓存比内存快。
-
页表换入换出的过程,什么是Swap机制
-
在 32 位/64 位操作系统环境下,申请的虚拟内存超过物理内存后会怎么样?
- 在 32 位操作系统,因为进程最大只能申请 3 GB 大小的虚拟内存,所以直接申请 8G 内存,会申请失败。
- 在 64 位操作系统,因为进程最大只能申请 128 TB 大小的虚拟内存,即使物理内存只有 4GB,申请 8G 内存也是没问题,因为申请的内存是虚拟内存。
程序申请的虚拟内存,如果没有被使用,它是不会占用物理空间的。当访问这块虚拟内存后,操作系统才会进行物理内存分配。
如果申请物理内存大小超过了空闲物理内存大小,就要看操作系统有没有开启 Swap 机制:
- 如果没有开启 Swap 机制,程序就会直接 OOM;
- 如果有开启 Swap 机制,程序可以正常运行。
-
内存页面置换算法
- 最佳页面置换算法
- 先进先出算法
- LRU
- 时钟页面置换算法
- 最不常用算法