Java面试八股文
类的加载顺序
1、静态成员/代码块
2、非静态成员/代码块
3、构造方法
子类的对象创建时,优先加载父类的代码块,与构造函数
总结
1、被static关键字所修饰的属性和方法 被整个程序共享,通过类名直接调用
2、静态方法中不能访问非静态变量和方法
3、在非静态方法中不能声明静态的局部变量
4、被static修饰的属性 优先被加载 优先于主方法
5、静态代码块只执行一次 优先于代码块和构造方法
6、静态代码块和静态变量同时存在时 按照先后顺序执行
重载重写区别
重载:一个类中多个同名方法根据不同的传参来执行不同的逻辑处理
重写:子类对父类方法的重新改造,方法名,参数列表相同构造函数无法重写。
重写的返回类型:如果是void和基本数据类型,则返回值重写时不能修改。如果为引用类型,则可以返回该引用类型的子类。
equals和==在堆栈中的体现
equals 比较的是值或者说是两个对象的内容是否相等
==是直接比较的两个对象的堆内存地址,如果相等,则说明这两个引用实际是指向同一个对象地址的。
基本类型 :比较的是值是否相等
引用类型 :引用数据类型,比较的是他们在堆内存地址是否相等。每新new一个引用类型的对象,会重新分配堆内存空间,比较返回false。
Java把内存划分成两种:一种是栈内存,一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
redis持久化方案
redis提供了2种持久化方案:RDB,AOF。
关闭redis server时,会将内存中的数据持久化到硬盘;启动redis server时,会从硬盘加载数据到内存;redis server运行时,每隔一段时间会自动同步内初中的数据到硬盘。
RDB(快照)
rdb是redis默认使用的持久化方案,隔一段时间同步一次,使用快照保存内存中的全量数据。
AOF(只追加文件)
Append Only File,aof是把执行过的写指令记录到一个.aof文件中(相当于写指令的日志),启动redis server时,把.aof中的写指令重新执行一遍,还原数据。
Spring Boot常用注解
1、@SpringBootApplication
替代 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
2、@MapperScan
spring-boot支持mybatis组件的一个注解,通过此注解指定mybatis接口类的路径,即可完成对mybatis接口的扫描。
3、@controller
表明这个类是一个控制器类
4、@RequestMapping
用来拦截请求,默认拦截get和post请求
@RequestMapping("/adminDetele/{id}") 或
@RequestMapping(value="/adminDetele/{id}", method= RequestMethod.GET )
5.@RestController
@RestController 是@Controller 和@ResponseBody的结合,以json数据格式返回数据,一个类被加上@RestController 注解,数据接口中就不再需要添加@ResponseBody。更加简洁。
servcie层注解
1.@Service
这个注解用来标记业务层的组件,我们会将业务逻辑处理的类都会加上这个注解交给spring容器管理,在需要使用的地方可使用@Autowired自动装配
@Service
public class ArticleServiceImpl implements ArticleService {}
@Controller
public class ArticleController {
@Autowired
ArticleService articleService;}
1.@Resource
@Resource和@Autowired一样都可以用来装配bean,都可以标注字段上,或者方法上。 @resource注解不是spring提供的,是属于J2EE规范的注解。
两个之前的区别就是匹配方式上有点不同,@Resource默认按照名称方式进行bean匹配,@Autowired默认按照类型方式进行bean匹配
线程池具体底层 七个参数以及解释 拒绝策略详细说说
ThreadPoolExecutor类
提供了四个构造方法,但是其余三个构造方法最后都调用7个参数的构造方法。
7个参数的含义
corePoolSize:核心线程池大小,创建对象后,池中默认是没有线程的,当有任务到达后才会创建线程执行,执行完后,线程就不销毁了。知道创建出于核心池子大小相等数量的线程。除非使用了prestartAllCoreThreads()或者prestartCoreThread()方法,线程池在任务没到来之前就会创建一个线程。
maximumPoolSize:表示线程池中最多能创建多少个线程。
keepAliveTime:表示线程没有任务执行后多久会进行销毁。默认情况下只有当线程数量大于核心池子时,才会起作用,直到线程池中的线程数量不超过corePoolSize。
unit:参数KeepAliveTime的时间单位,有7种取值,在TimeUnit类中有 7中静态属性(天、小时、分钟、秒、毫秒、微妙、纳秒)
workQueue:一个阻塞队列,用来存储等待执行的任务,这个参数的选择很重要,会对线程池的运行过程产生重大影响。
threadFactory:创建工厂用来创建线程。
handler:表示线程池的拒绝策略,有四种。
线程池的拒绝策略
线程池提供了四种类型的拒绝策略
AbortPolicy策略,会直接抛出异常
CallerRunsPolicy策略,只要线程池未关闭,该策略在调用线程中运行当前任务(如果任务被拒绝了,则由提交任务的线程(例如main)直接执行此任务)
DiscardOledestPolicy策略,丢弃最老的请求,尝试再次提交当前任务。
DiscardPolicy策略,丢弃无法处理的任务,不予任何处理。
String,StringBuilder,StringBuffer的区别
# | String | StringBuffer | StringBuilder |
---|---|---|---|
执行速度 | 最差 | 其次 | 最高 |
线程安全 | 线程安全 | 线程安全 | 线程不安全 |
使用场景 | 少量字符串操作 | 多线程环境下的大量操作 | 单线程环境下的大量操作 |
StringBuffer使用了synchronize关键字,对方法进行了同步处理。因此StringBuffer适用于多线程环境下的大量操作。
springboot用什么和MySQL集成
1.引入mybatis和mysql的依赖
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
2.添加配置文件配置数据库和其他参数
在resource文件夹下添加application.properties配置文件并输入数据库参数,如下:
#mysql配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
Redis为什么是单线程的
1、单线程模式方便开发和调试;
2、Redis内部使用了基于epoll的多路复用;
3、Redis主要的性能瓶颈是内存或网络带宽。
Redis在5.0后为什么引入了多线程
Redis在I/O事件处理上,采用了I/O多路复用技术,同时监听多个套接字,并为套接字关联不同的事件处理函数,通过一个线程实现了多客户端并发处理。核心依旧时单线程。
JVM垃圾回收机制
GC (Garbage Collection:即垃圾回收)的基本原理:将内存中不再被使用的对象进行回收,GC中用于回收的方法称为收集器,由于GC需要消耗一些资源和时间,Java在对对象的生命周期特征进行分析后,按照新生代、老年代的方式来对对象进行收集,以尽可能的缩短GC对应用造成的暂停
jdk默认用的哪个回收器
UseParallelGC 即 Parallel Scavenge + Parallel Old
CMS垃圾回收器
CMS垃圾回收器的名字是(Ccrrent Mark Sweep并发标记清除),是一款采用标记清理算法回收老年代的垃圾回收器!
它的过程可以分为以下6个步骤:
初始标记(STW initial mark)
并发标记(Concurrent marking)
并发预清理(Concurrent precleaning)
重新标记(STW remark)
并发清理(Concurrent sweeping)
并发重置(Concurrent reset)
会出现的问题
1.CMS收集器对处理器资源非常敏感
CMS的垃圾清除是使用并发清除的,如果处理器核数不高,垃圾回收会造成很大负担
2.CMS无法处理浮动垃圾
就是并发清理阶段用户线程还在运行,这段时间就可能产生新的垃圾,新的垃圾在此次GC无法清除,只能等到下次清理。这些垃圾就叫浮动垃圾
3.CMS是基于标记清除算法,会产生大量的碎片空间
乐观锁和悲观锁
乐观锁通常是通过在表中增加一个版本(version)或时间戳(timestamp)来实现,其中,版本最为常用。
乐观锁每次在执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 +1 操作,否则就执行失败。
利用悲观锁的解决思路是,我们认为数据修改产生冲突的概率比较大,所以在更新之前,我们显示的对要修改的记录进行加锁,直到自己修改完再释放锁。加锁期间只有自己可以进行读写,其他事务只能读不能写。