《互联网大厂Java面试:核心知识大考验》

26 阅读7分钟

面试官:请简要介绍一下Java核心知识中的面向对象三大特性。

王铁牛:嗯,面向对象三大特性就是封装、继承和多态嘛。封装就是把数据和操作数据的方法封装在一起,继承就是子类继承父类的属性和方法,多态就是同一个行为具有多个不同表现形式。

面试官:不错,回答得挺清晰。那说说JUC里的CountDownLatch是怎么用的?

王铁牛:这个嘛,CountDownLatch可以用来让一个线程等待其他多个线程完成任务后再执行。比如说有多个线程去处理一些任务,主线程可以通过CountDownLatch来等待这些线程都处理完,然后再继续执行后续逻辑。

面试官:很好。再问个关于JVM的问题,简述一下垃圾回收机制。

王铁牛:垃圾回收机制就是回收那些不再使用的对象所占用的内存空间。有几种常见的算法,像标记清除、标记整理、复制算法之类的,哎呀,具体细节我也不太清楚了。

第二轮

面试官:多线程中如何保证线程安全?

王铁牛:可以用synchronized关键字来同步代码块或者方法,还有就是用Lock接口及其实现类。

面试官:那线程池的核心参数都有哪些?

王铁牛:有corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue和threadFactory这些。

面试官:说说HashMap的底层数据结构。

王铁牛:HashMap底层是数组加链表再加红黑树,当链表长度超过一定阈值就会转换成红黑树来提高查询效率。

第三轮

面试官:Spring框架中Bean的生命周期是怎样的?

王铁牛:这个嘛,就是先实例化,然后设置属性,接着如果实现了BeanNameAware接口会调用相关方法,再然后是BeanPostProcessor前置处理,之后是InitializingBean的afterPropertiesSet方法或者自定义的init-method方法,最后是BeanPostProcessor后置处理。

面试官:Spring Boot自动配置原理是什么?

王铁牛:Spring Boot通过条件注解来自动配置,根据类路径下的依赖和配置来决定配置哪些Bean。

面试官:MyBatis的缓存机制了解吗?

王铁牛:不太清楚,好像有一级缓存和二级缓存,具体怎么回事我不太明白。

面试结束,面试官表示会让王铁牛回家等通知。

答案

  • 面向对象三大特性
    • 封装:将数据和操作数据的方法封装在一起,对外提供统一的访问接口,隐藏内部实现细节,提高数据的安全性和程序的可维护性。
    • 继承:子类继承父类的属性和方法,实现代码复用,提高软件的可扩展性。
    • 多态:同一个行为具有多个不同表现形式,比如方法重载和方法重写。方法重载是在同一个类中定义多个同名但参数不同的方法;方法重写是子类对父类的方法进行重新实现,以满足不同的需求。
  • CountDownLatch的使用
    • 例如有一个任务需要多个子任务完成后才能执行。创建一个CountDownLatch对象,传入需要等待的子任务数量。每个子任务完成后调用CountDownLatch的countDown方法,主线程调用CountDownLatch的await方法等待,直到计数器变为0,主线程才会继续执行。
  • 垃圾回收机制
    • 标记清除算法:先标记出所有需要回收的对象,然后统一回收这些对象所占用的内存空间。缺点是会产生大量不连续的内存碎片。
    • 标记整理算法:标记出需要回收的对象后,将存活对象向一端移动,然后直接清理掉端边界以外的内存。
    • 复制算法:将内存空间分为两块,每次只使用其中一块,当这一块内存使用完后,将存活对象复制到另一块内存,然后清理原来的内存块。适用于对象存活率低的场景。
  • 多线程保证线程安全的方法
    • synchronized关键字:可以修饰代码块或方法,确保同一时刻只有一个线程能访问被修饰的代码块或方法。
    • Lock接口及其实现类:如ReentrantLock,提供了比synchronized更灵活的锁控制,例如可中断锁、公平锁等。
  • 线程池的核心参数
    • corePoolSize:线程池的核心线程数,当提交的任务数小于corePoolSize时,线程池会创建新线程来执行任务。
    • maximumPoolSize:线程池允许的最大线程数,当提交的任务数大于corePoolSize且workQueue已满时,会创建新线程直到线程数达到maximumPoolSize。
    • keepAliveTime:线程池中非核心线程的存活时间,当线程数大于corePoolSize时,非核心线程在空闲一段时间后会被销毁,这个空闲时间就是keepAliveTime。
    • unit:keepAliveTime的时间单位。
    • workQueue:线程池中的任务队列,用于存放提交的任务,当线程数达到corePoolSize时,新提交的任务会放入workQueue中。
    • threadFactory:用于创建线程的工厂,可以自定义线程的名称、优先级等属性。
  • HashMap的底层数据结构
    • 初始是一个数组,每个数组元素是一个链表节点。当向HashMap中插入元素时,通过计算key的哈希值找到对应的数组位置,如果该位置为空,则直接插入新节点;如果不为空,则遍历链表,若找到相同key的节点则更新其value,若未找到则在链表尾部插入新节点。当链表长度超过一定阈值(默认为8)且数组长度大于64时,链表会转换成红黑树,以提高查询效率。
  • Spring框架中Bean的生命周期
    • 实例化:通过反射创建Bean的实例。
    • 设置属性:根据配置文件或注解等方式为Bean的属性赋值。
    • BeanNameAware:如果Bean实现了BeanNameAware接口,会调用setBeanName方法,传入Bean的名称。
    • BeanPostProcessor前置处理:执行BeanPostProcessor的postProcessBeforeInitialization方法,对Bean进行前置处理。
    • InitializingBean和自定义init-method:如果Bean实现了InitializingBean接口,会调用afterPropertiesSet方法;也可以通过配置文件中的init-method指定自定义的初始化方法。
    • BeanPostProcessor后置处理:执行BeanPostProcessor的postProcessAfterInitialization方法,对Bean进行后置处理。
  • Spring Boot自动配置原理
    • Spring Boot通过条件注解(如@Conditional系列注解)来实现自动配置。它会根据类路径下的依赖和配置信息,自动判断需要配置哪些Bean。例如,如果类路径下存在某个特定的依赖,就会自动配置与之相关的Bean。通过这种方式,大大简化了Spring应用的配置过程,开发者只需要引入必要的依赖,Spring Boot就能自动完成大部分的配置工作。
  • MyBatis的缓存机制
    • 一级缓存:是SqlSession级别的缓存,在同一个SqlSession中,对相同的SQL语句执行查询,第一次会从数据库查询并缓存结果,后续相同查询直接从缓存中获取数据,不会再次查询数据库。当SqlSession关闭时,一级缓存会被清空。
    • 二级缓存:是Mapper级别的缓存,多个SqlSession可以共享二级缓存。开启二级缓存后,对于同一个Mapper的查询,不同的SqlSession会先从二级缓存中查询数据,如果缓存中没有则再查询数据库,并将查询结果缓存到二级缓存中。二级缓存的有效期更长,适用于多个用户共享数据的场景。