JAVA面试知识点
2025-08-21 10:37:45 6 举报
AI智能生成
简述Java面试大概知识点
作者其他创作
大纲/内容
Java基础
基本类型
整数类型:byte、short、int、long
浮点类型:float、double
字符类型:char
布尔类型 :boolean
集合数组
集合
Collection(存储对象)
list(有序,可重复)
ArrayList
LinkedList
Vector
set(无序,唯一)
HashSet(无序)
LinkedHashSet(维护顺序有序)
TreeSet(元素有序)
queue
Map(存储键值对key-value)
HashTable
ConcurrentHashMap
HashMap
数组
String
子主题
string、集合、数组的相互转换。
数组转换为集合:Arrays.asList()
集合转换为数组:Collections.toArray()
字符串转换为数组:split()
数组转换为字符串:Arrays.toString()
运行时异常:
NullPointerException:当尝试使用null对象引用进行操作时
ArithmeticException:当发生数学运算错误时,如除数为0。
IllegalArgumentException:当向方法传递非法或不适当的参数时
ClassCastException:当尝试将对象强制转换为不是实例的子类时
ArithmeticException:当发生数学运算错误时,如除数为0
NoSuchMethodException:当尝试访问不存在的方法时
异常: 自定义异常:用户可以自定义异常类,继承自Exception类,以表示特定的错误情况。例如,DivideByMinusException,当被除数为负数时抛出。
非运行时异常:
FileNotFoundException:当尝试读取不存在的文件时。
IOException:在文件读写过程中发生错误。
SQLException:在数据库访问过程中
EOFException:当预期中应该读取更多数据时却到达文件末尾时。
throw与throws的区别
常用的关键字
synchronized
面向对象基本特点
封装
含义:属性私有化,同时提供被外界访问的方法。
好处:1|良好的封装可以解耦合,2、类内部可以自由修改3、隐藏信息实现细节。
继承
多态
父类引用子类的对象
实现
重载(运行时多态)
重写(编译时多态)
关系型数据库Mysql,磁盘存储
索引的分类1
聚簇索引:将数据与索引存储放到一块。
非聚簇索引:将数据与索引分开存储。
索引的分类2
主键索引
唯一索引
复合索引
全文索引
空间索引
前缀索引
索引
存储引擎
InnoDB
MyISAM
不同
索引底层数据结构
哈希:查询一条记录。
有序数组:等值查询与范围查询。
B+树
索引创建的原则
针对于数据量较大,且查询比较频繁的表建立索引。
针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引
如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
索引的失效场景
(1)如果条件中有or,即使其中有条件带有索引也不会使用(除非or条件每个列都加有索引),这也是为什么尽量少用or的原因。
(2)复合索引未用左列字段。
(3)Like以%开头
(4)Where中索引列有运算或使用了函数。
(6)如果mysql觉得全盘扫描更快时(数据少).
Mysql超大分页处理:数据量超大时,使用limit 分页时,需要对所有数据进行排序,效率低。
解决方案:覆盖索引+子查询
事务(InnoDB唯一支持事务的引擎)
事务是一系列的数据库操作,是数据库应用的基本单位,要么完全执行,要么完全不执行。
事务的4个特性:
一致性(Consistency):事务的执行使得数据库从一种正确状态转化为另一种正确状态。
隔离性(Isolation):在事务正确提交之前,不允许把对数据的任何改变提供给其他事务。
持久性(Durability):事务提交后,其结果永久的保存到数据库中。
原子性(Atomicity):事务包含的操作要么全部成功,要么全部失败回滚。
隔离级别:
读未提交:一个事务可以读取另一个未提交事务的数据(脏读)。
读已提交(rc):就是一个事务要等另一个事务提交后才能读取数据。读操作事务要等待这个更新操作事务提交以后才能读取事务,可以解决脏读问题。但在 这个事例中,出现了一个事务范围内两个相同的查询却返回不同的结果(不可重复读)。
可重复读(rr mysql默认隔离级别):开始读取数据时,不再允许修改操作。解决了不可重复读问题,不可重复读对应的是修改,即update操作。但是还可 能会出现幻读问题。因为幻读对应的是insert插入操作,不是update问题。
序列化 : 最高的事务隔离级别,在该级别下事务串行化顺序执行,避免了那三个问题,但是效率低下,比较耗数据库性能。一般不使用。
MVCC(多版本并发控制):
RC级别下:在事务启动前构建事务一致性视图
RR级别下:在执行sql语句前开启事务一致性试图。
语法
select:select name,age from t1 where 条件;
update: update t1 set xxx=xxx,xxx=xxx where 条件;
delete: delete from t1 where 条件;
insert:insert into t1(字段1名,字段2名) values(值1,值2),(值1,值2),(值1,值2);
优化
定位慢查询
表象:页面加载过慢,接口压测使用时间过长。
方法:
开源工具:1、调试工具:Athras。2、运维工具:Skydivingwalking。
Mysql自带慢日志。
sql执行计划(找到慢的原因)
explain 命令 explain +SQL语句。会输出sql语句的执行信息。
possible -key :当前sql可能会使用到的索引。
key:当前使用的索引。key_len:索引占用大小。可以用这两个判断是否可能命中索引。
extra:额外的优化建议。Using where;Using Index 使用索引,不需要回表。 Using Index condition 使用索引,需要回表。
type:SQL的性能。
SQL优化经验
表的设计优化
索引优化
Mysql语句优化
主从复制、读写分离(访问压力)
核心:二进制日志(记录了所有的DDL语句(数据库定义语言),以及DML语句(数据库操作语言),但不包括查询语句)。
过程:
1、主库在事务提交时,会把数据库变更记录在二进制日志文件binlog中
2、从库读取主库的二进制日志文件,写道从库的中继日志Relay Log中
3、从库重新做日志中的事件,改变自己的数据。
分库分表(单表数据量达到20g、数据1000w)
分库
垂直分库:以表为依据,按业务将不同的表拆分到不同库中。eg:用户表、订单表、商品表。
水平分库:将一个库的数据,拆分到多个库中,解决了单库大数量,高并发的性能瓶颈问题,提高了系统的稳定性和可用性。
分表
水平分表:将一个表的数据拆分到多个表中(可以同一个库,也可以不同库)
垂直分表:以字段为依据,根据字段不同属性拆分到不同表中。将不常用的字段单独放在一张表中。
新的问题和技术:
约束:MySQL事务约束是指在数据库操作过程中,对数据的一致性、完整性和可靠性进行保障的一种机制
主键约束(Primary key)
外键约束(Foreign key)
唯一约束(Unique)
非空约束(Not Null)
检查约束:(check)
约束的添加与删除
主键和外键的区别:
mysql存储过程:是一组为了完成特定功能的SQL语句集合。它们被编译和优化后存储在数据库服务器中,可以被外部程序调用。使用存储过程的目的在于将常用或复杂的SQL工作预先定义好,并存储起来,以便需要时可以重复使用。
创建一个存储过程
调用存储过程
注意事项以及好处
JVM虚拟机
Java从编译到执行到执行的过程
编译
类加载
加载
连接
- 验证
- 准备
- 解析
初始化
解释
执行
双亲委派
java中的类加载器
Bootstrap ClassLoader (启动类加载器)
Extension ClassLoader(拓展类加载器)
Application ClassLoader (应用程序类加载器)
User ClassLoader(自定义类加载器)
双亲委派机制
使用双亲委派的原因
打破双亲委派
在自定义类加载器中,重写LoaderClass类中loadClass方法
使用线程上下文类加载器
打破双亲委派的场景
tomcat
jdbc
JVM内存结构(JVM定义的运行时数据区域)
程序计数器
虚拟机栈
定义
生命周期
作用
特点
基本存储单位栈帧
局部变量表(或本地变量表)
操作数栈(或表达式栈)
动态链接(或指向运行时常量池的方法引用)
方法返回地址(或方法正常退出或者异常退出的定义)
一些附加信息
通过使用-Xss参数调整栈的大小
本地方法栈
方法区(线程共享)
方法区(永久代、元空间辨析)
取消永久代的原因
存储
堆(线程共享)
gc垃圾回收
判断对象不在使用
引用计数法
可达性分析法(gc roots)
gc roots一般是什么
虚拟机栈(栈帧中的本地变量表)中引用的对象
本地方法栈中 JNI(即一般说的 Native 方法)引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
分代的理由
常见的垃圾回收器
年轻代:seria(单线程)、parallel Scavenge(多线程)、parNew
老年代:seria old、parallel old、CMS
常见的垃圾回算法
标记清除
标记复制
标记整理
对象什么时候才到老年代
对象太大了直接进入老年代,survivor放不下
如果对象太老了,就会直接晋升老年代。(每发生一次minor GC ,存活的对象年龄+1,达到默认值15,就会晋升至老年代。
触发Minor GC
解决跨代引用
卡表
CMS垃圾回收器
特点
1、在在GC线程工作的时候,用户线程不会完全停止,在部分场景下与GC线程并发执行。
2、减少Stop the world时间 (即设计目的)
标记清除垃圾回收算法。
CMS垃圾回收过程
初始标记(会发生stw)
并发标记(不会发生stw)
(预处理)(不会发生stw)
重新标记(会发生stw)
并发清除(不会发生stw)
缺点
空间需要预留
浮动垃圾
内存碎片
G1垃圾回收器
划分:空间划分是以逻辑形式
空间分布
G1垃圾回收过程
网络相关
建立连接与断开连接
三次握手
过程
原因
四次挥手
过程
原因
TCP与UDP
TCP:面向连接的可靠性传输,传输形式是字节流,传输效率慢,所需资源多,场景:要求通信数据可靠,如:发送和接收邮件、文件远程传输。
UDP:无连接,传输形式是报文字段,场景要求通信速度高如:qq语音、直播等。
get和post的区别
get重点是在服务器获取资源,post是向服务器发送数据。
get传输数据是通过URL请求,这个对用户是可见的。post传输数据通过Http的post机制,将字段与对应值封存在请求实体中发送给服务器,这个过程对用户是不可见的
get上传数据量小因为url长度是有限的,而post可以上传大量数据。
get是不安全的,post是安全的
get只支持ASCII字符,而post支持标准字符集。
跟踪浏览器用户身份
cookies:客户端
session:服务器端
https是如何工作的
线程
线程
创建线程的方式:
1、继承Thread类。
2、实现Runnable接口。
3、实现Callable接口
线程和进程的区别:
解释上下文切换:
线程池
什么是线程池:
使用线程池的原因:
线程池的核心参数:
corePoolSize:核心线程数,线程池维护线程的最少数量题
maximumPoolSize:最大线程数,线程池维护线程的最大数量。
keepAliveTime:非核心线程的空闲存活时间,超过该时间则非核心线程被回收。
workQueue:任务队列,用于存放待执行的任务
threadFactory:线程工厂,用于创建线程。
handler:拒绝策略,当线程池无法处理更多任务时,用于决定如何处理。
线程池的类型:
ExecutorService:通用线程池,支持定时任务、线程优先级设置等。
SingleThreadExecutor:单线程执行器,仅有一个线程执行任务,适用于轻量级任务。
ThreadPoolExecutor:适用于并发执行大量任务,可自定义线程池的各种参数
ScheduledThreadPoolExecutor:支持定时任务的线程池。
ForkJoinPool:适用于计算密集型任务,可以充分利用多核CPU的计算能力
使用线程池的步骤:
线程池的创建方式:
1、使用ThreadPoolExecutor类手动创建:ThreadPoolExecutor是Java提供的最灵活的线程池创建方式。用户可以自定义线程池的各种参数,如核心线程数、最大线程数、线程空闲时间等。
2、使用Executors类的工厂方法创建:Java的Executors类提供了一系列静态方法,可以用来创建不同类型的线程池,如固定大小的线程池(newFixedThreadPool)、可缓存的线程池(newCachedThreadPool)和单个线程的线程池(newSingleThreadExecutor)
3、通过Spring框架创建:Spring框架提供了对线程池的支持,可以在Spring的配置文件中配置线程池,或者使用Spring的依赖注入功能来创建线程池。
4、通过Guava库创建:Google的Guava库中也提供了线程池的实现,可以用来创建和管理线程池。
5、除了上述创建方式,还有其他一些特定的线程池创建方式,如单线程定时线程池(SingleThreadScheduledExecutor)和抢占式线程池(WorkStealingPool,这是在JDK 1.8中引入的)
SSM以及SpringBoot
spring
spring中的bean是线程安全的么?
AOP
含义(动态代理):面向切面编程,将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合。
使用场景:
spring的事务是如何实现的:
事务失效的场景:
1、异常捕获处理,自己处理了异常,没有抛出 解决:手动抛出。
2、抛出检查异常 配置rollbackFor属性为Exception
3、非 public方法导致事务失效
bean的生命周期
通过beanDefinition获取bean的定义信息
调用构造函数,实例化bean(一般是无参构造函数)
bean的依赖注入也就是给对象设置属性(set方法)
处理aware接口(beanNameAware、BeanFactoryAware、ApplicationContextAware)
bean的后置处理器--前置
bean的初始化(init-method配置初始化方法)
bean的后置处理器--后置
对象销毁
ioc容器关闭
Spring中的循环引用
循环依赖:循环依赖其实就是循环引用,也就是两个或两个以上的bean互相持有对方,最终形成闭环,eg:A依赖B,B依赖A
循环依赖在spring中是允许存在的,spring框架依据三级缓存已经解决了大部分的循环依赖。
一二级缓存可以解决普通对象大部分循环依赖,但当对象是代理对象时,一二缓存不可以需要三级
三级缓存
一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象
二级缓存:缓存早期的bean对象(生命周期还没走完)
三级缓存:缓存的是ObjectFactory,表示对象工厂,用来创建某个对象。
注入的方式是构造函数时:
由于bean的生命周期中构造函数是第一个执行的,spring框架并不能解决构造函数的依赖注入
解决: 使用@Lazy进行懒加载,什么时候需要对象在进行bean对象的创建。
springMVC
执行过程:
视图阶段(老旧JSP等)
前后端分离阶段(接口开发、异步)
springBoot
自动配置原理:
在Spring Boot项目中的引导类上有一个注解@SpringBootApplication, 这个注解封装了三个注解。@SpringBootConfiguration @EnableAutoConfiguration@ComponentScan
其中@EnableAutoConfiguration 是实现自动化配置的核心注解,该注解通过@import 注解导入对应的配置选择器----->就是读取了该项目和项目引用的Jar包的CLasspath路径下的META-INF/Spring.factories文件中的所配置类的全类名。在这些配置类中所定义的Bean会根据条件注解所指定的条件来决定是否将其倒入到Spring容器中(按需加载)
条件判断,会有像@ConditionalOnClass这样的注解,判断是否有对应的字节码class文件,有则按需加载,把这个配置类的所有Bean放入spring容器中。
常用注解
Spring
SpringMVC
Spring Boot
Mybatis
执行流程:
延迟加载及其使用原理:
Mybatis支持延迟加载,但是默认没有开启
含义:延迟加载也可以认为是按需加载。就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。
底层原理:
一二级缓存:
Redis,(基于内存存储,读写性高)
缓存
穿透、击穿、雪崩
缓存雪崩
造成的原因(含义)
解决方法
为避免redis宕机造成缓存雪崩,可以布置redis集群。
尽量不用设置相同的过期时间,可以在原有的时间上加上一个随机值
降低服务,当流量到达一定的阈值时,就直接返回“系统繁忙”之类的提示,防止过多的请求打在数据库上,这样虽然难用,但至少可以使用,避免直接把数据库搞挂
缓存穿透
造成的原因(含义)
解决方法
空缓存,key不存在直接返回null,但是会造成其他问题。
布隆过滤器
对用户的id校验,校验他的合法性
缓存击穿
造成的原因(含义)
解决方法
对热点的key不设置超时时间。
加锁,只有拿到锁的请求才可以访问的数据库,然后缓存到redis中
缓存一致性
延时双删(延时不太确定,在延迟过程中可能会出现脏数据,并不能保证强一致性。)
(缓存失败的情况)重试机制,利用MQ中间件,更新数据库之后,通知缓存删除
(缓存失败的情况)利用canal中间件,不需要修改业务代码,伪装为mysql的一个从节点,cannal通过读取binlog数据更新缓存。
redission实现的读写锁(强一致性),但是性能较低。
共享锁:读锁readLock,加锁之后,其他线程可以共享读操作。
排他锁:独占锁writeLock,加锁之后,阻塞其他线程读写操作。
持久化
RDB,redis数据备份文件,也叫redis数据快照,就是把内存中的所有数据记录到磁盘。当redis实例故障重启后,从磁盘读取快照文件,恢复数据。
AOF,追加文件。redis处理每一个命令都会记录在AOF文件,可以看作是命令日志文件。恢复数据时在执行一遍命令。
数据淘汰策略:redis内存不够用时,此时向redis添加新的key,redis会按照一定的策略将内存中的数据删掉。
LRU:最近最少使用,当前时间减去最后一次访问时间,值越大淘汰优先级越高。
LFU:最少频率使用,统计每个key的访问频率,值越小淘汰优先级越高。
过期策略
惰性删除
定期删除
分布式锁
如何实现:redission分布式锁,底层是用setnx+lua脚本实现(lua作用是保证了原子性)
如何控制有效时长:watchdog(看门狗)机制,主动给持有锁的线程的锁过期时间续期。
可重入锁:可重入锁,多个线程重入需要判断是否是当前线程,在redis中进行存储的时候使用hash结构,来存储线程信息和重入次数。
主从一致问题:不能解决,但是可以使用redission提供的红锁,但这样的话性能太低了,如果必须保持一致性,可以用zookeeper实现分布式锁。
使用场景:集群情况下的定时任务、抢单、幂等性
基本类型
string
子主题
子主题
list(与顺序有关的数据 eg:朋友圈)
hash(存储一些对象)
set(不能有重复运算,eg:集合、交集、关注、互相关注)
zset(eg:热顶排行)
集群方案
主从复制
哨兵模式
分片集群
0 条评论
下一页