Java开发工程师(12K级别)面试宝典

52 阅读11分钟

一、Java 基础 (核心重点)​

  1. ​面向对象的三大特性是什么?请详细解释,并举例说明。​

    • ​封装​​:将对象的属性和行为封装起来,不需要让外界知道具体实现细节,通过提供的方法来访问和操作对象。例如:一个Person类的age属性,通过setAge()方法进行设置,可以在方法内加入逻辑判断防止年龄被设置为负数。
    • ​继承​​:子类继承父类的特征和行为,使子类具有父类的属性和方法,从而达到代码重用的目的。例如:Dog类继承Animal类,拥有Animaleat()方法。
    • ​多态​​:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。主要包括​​重写(Override)​​ 和​​重载(Overload)​​。例如:父类AnimalmakeSound()方法,子类DogCat分别重写该方法,调用时表现出不同的叫声。
  2. ​== 和 equals() 的区别?​

    • ​==​​:是运算符。对于基本数据类型,比较的是​​值​​是否相等;对于引用数据类型,比较的是对象在​​内存中的地址​​(即是否是同一个对象)。
    • ​equals()​​:是Object类的方法,默认行为也是比较​​内存地址​​。但很多类(如StringInteger)重写了equals()方法,使其比较的是对象的​​内容​​是否相等。
  3. ​String, StringBuffer, StringBuilder 的区别?​

    • ​String​​:不可变字符序列。任何修改操作都会生成新的String对象。​​线程安全​​。
    • ​StringBuffer​​:可变字符序列。修改操作在原有对象上进行。方法用synchronized修饰,​​线程安全​​,但效率相对较低。
    • ​StringBuilder​​:可变字符序列。与StringBuffer API兼容,但​​线程不安全​​,效率最高。
    • ​使用场景​​:操作少量数据用String;单线程下操作大量数据用StringBuilder;多线程下操作大量数据用StringBuffer。
  4. ​接口和抽象类的区别?​

    特性抽象类 (Abstract Class)接口 (Interface)
    方法可以有抽象方法和具体方法Java 8前只能是抽象方法,之后可以有defaultstatic方法
    变量可以有成员变量只能是public static final常量
    继承单继承(一个类只能继承一个抽象类)多实现(一个类可以实现多个接口)
    构造器
    设计目的​is-a​​ 关系,表示类的本质​has-a​​ 关系,表示类的功能
  5. ​简述Java的异常体系?Error和Exception有什么区别?​

    • ​Throwable​​ 是所有错误和异常的超类。

      • ​Error​​:是程序无法处理的严重错误,表示运行应用程序中较严重问题。通常与代码编写者无关,而是JVM出现的问题。例如:OutOfMemoryErrorStackOverflowError。不可捕获处理。

      • ​Exception​​:是程序本身可以处理的异常。分为​​运行时异常(RuntimeException)​​ 和​​编译时异常(Checked Exception)​​。

        • ​运行时异常​​:如NullPointerExceptionIndexOutOfBoundsException,编译器不要求强制处理。
        • ​编译时异常​​:如IOExceptionSQLException,编译器要求必须用try-catch捕获或throws声明。

​二、集合框架 (Collections Framework)​

  1. ​HashMap 的原理是什么?如何解决哈希冲突?​

    • ​原理​​:基于哈希表(数组+链表/红黑树)实现。存储时,根据key的hashCode()计算数组下标。获取时,同样根据hashCode找到数组下标,再遍历链表或红黑树比较key是否相等。

    • ​解决哈希冲突​​:

      1. ​链表法​​(JDK 1.7):相同下标的元素组成一个单向链表。
      2. ​链表+红黑树​​(JDK 1.8+):当链表长度超过阈值(默认为8)且数组长度大于64时,链表会转换为红黑树,以提高查询效率(O(n) -> O(log n))。当树节点数小于6时,会退化为链表。
  2. ​HashMap 和 Hashtable 的区别?​

    • ​线程安全​​:​​Hashtable​​是线程安全的(方法用synchronized修饰),​​HashMap​​是线程不安全的。
    • ​Null键/值​​:​​HashMap​​允许key和value为null;​​Hashtable​​不允许。
    • ​性能​​:由于Hashtable的同步开销,​​HashMap​​的性能通常优于Hashtable。
    • ​推荐​​:基本淘汰Hashtable,多线程环境下常用ConcurrentHashMap
  3. ​List 接口下,ArrayList 和 LinkedList 的区别?​

    • ​底层结构​​:

      • ArrayList:基于​​动态数组​​。
      • LinkedList:基于​​双向链表​​。
    • ​操作效率​​:

      • ​随机访问 (get/set)​​:ArrayList效率高(O(1)),LinkedList效率低(O(n))。

      • ​增删操作 (add/remove)​​:

        • 在​​尾部​​操作,两者效率相近。
        • 在​​中间​​指定位置插入/删除,LinkedList效率更高(O(1),但需先遍历到位置O(n)),ArrayList需要移动后续所有元素(O(n))。

​三、多线程与并发​

  1. ​创建线程有哪几种方式?​

    1. 继承Thread类,重写run()方法。
    2. 实现Runnable接口,实现run()方法(​​推荐​​,避免单继承局限,利于资源共享)。
    3. 实现Callable接口,结合FutureTask使用,可以获取返回值。
    4. 使用线程池创建(如ExecutorService)。
  2. ​Runnable 和 Callable 有什么区别?​

    • Runnablerun()方法没有返回值,也不能抛出受检异常。
    • Callablecall()方法可以有返回值,并且可以抛出异常。
  3. ​sleep() 和 wait() 有什么区别?​

    • ​所属类​​:sleep()Thread的静态方法;wait()Object的实例方法。
    • ​锁释放​​:sleep()​不会释放​​当前线程持有的锁;wait()​会释放​​锁,并让线程进入等待池。
    • ​使用场景​​:sleep()用于暂停执行;wait()用于线程间通信。
  4. ​synchronized 和 ReentrantLock 有什么区别?​

    • ​本质​​:synchronized是JVM层面的关键字;ReentrantLock是JDK提供的API类。

    • ​功能​​:ReentrantLock更灵活,提供更多功能,如:

      • ​公平锁​​:可以选择公平锁或非公平锁(synchronized是非公平锁)。
      • ​可中断​​:lockInterruptibly()可以响应中断。
      • ​尝试获取锁​​:tryLock()可以尝试获取锁,获取不到直接返回。
      • ​多条件绑定​​:可以绑定多个Condition对象,实现更精细的线程唤醒。
  5. ​什么是线程池?为什么使用它?核心参数有哪些?​

    • ​是什么​​:管理一组工作线程的池子。它是一种池化技术,避免频繁创建和销毁线程的开销。

    • ​为什么​​:​​降低资源消耗​​(复用已创建的线程)、​​提高响应速度​​(任务到来时无需等待线程创建)、​​提高线程的可管理性​​(统一分配、调优和监控)。

    • ​核心参数​​(以ThreadPoolExecutor为例):

      1. corePoolSize:核心线程数。
      2. maximumPoolSize:最大线程数。
      3. keepAliveTime:非核心线程空闲存活时间。
      4. workQueue:任务队列(如ArrayBlockingQueueLinkedBlockingQueue)。
      5. threadFactory:线程工厂,用于创建线程。
      6. handler:拒绝策略(当线程池和队列都满了时如何处理新任务)。

​四、JVM 内存与GC​

  1. ​说一下 JVM 的主要组成部分及其作用?​

    • ​类加载器(ClassLoader)​​:加载.class文件到内存。
    • ​运行时数据区(Runtime Data Area)​​:JVM管理的内存区域。
    • ​执行引擎(Execution Engine)​​:解释/编译字节码,将其转换为机器指令执行。
    • ​本地方法接口(Native Interface)​​:调用本地(C/C++)方法库。
  2. ​描述一下 JVM 的内存模型(运行时数据区)?​

    • ​线程私有​​:

      • ​程序计数器​​:当前线程所执行的字节码的行号指示器。
      • ​虚拟机栈​​:存储Java方法执行时的栈帧(局部变量表、操作数栈、动态链接、方法出口等)。
      • ​本地方法栈​​:为Native方法服务。
    • ​线程共享​​:

      • ​堆​​:存放​​对象实例​​和数组,是GC管理的主要区域。
      • ​方法区​​:存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码等。JDK 8后称为​​元空间(Metaspace)​​,使用本地内存。
  3. ​如何判断对象是否可以回收?​

    • ​引用计数法​​(Java未采用):存在循环引用问题。
    • ​可达性分析算法​​(Java采用):从一系列“GC Roots”对象作为起点向下搜索,走过的路径称为“引用链”。如果一个对象到GC Roots没有任何引用链相连,则证明此对象不可用,可以被回收。
  4. ​说一下你知道的垃圾回收算法?​

    • ​标记-清除​​:标记所有需要回收的对象,然后统一清除。​​问题​​:产生内存碎片。
    • ​复制​​:将内存分为两块,每次只使用一块。当这一块用完了,就将还存活的对象复制到另一块上,然后一次性清理已使用的内存。​​优点​​:无碎片。​​缺点​​:内存利用率低。
    • ​标记-整理​​:标记过程与“标记-清除”一样,但后续不是直接清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
    • ​分代收集​​(​​现代商用VM常用策略​​):根据对象存活周期的不同将堆内存划分为​​新生代​​(Young Generation)和​​老年代​​(Old Generation)。新生代采用​​复制​​算法,老年代采用​​标记-清除​​或​​标记-整理​​算法。

​五、数据库 (MySQL)​

  1. ​事务的四大特性(ACID)是什么?​

    • ​原子性(Atomicity)​​:事务是一个不可分割的工作单位,要么全部成功,要么全部失败回滚。
    • ​一致性(Consistency)​​:事务执行前后,数据库的完整性约束没有被破坏。
    • ​隔离性(Isolation)​​:多个并发事务之间相互隔离,互不干扰。
    • ​持久性(Durability)​​:事务一旦提交,其对数据库的修改就是永久性的。
  2. ​MySQL 的索引是什么?有什么作用?​

    • ​是什么​​:索引是帮助MySQL高效获取数据的​​排好序的数据结构​​。
    • ​作用​​:大大加快数据的检索速度(​​查询优化​​)。
    • ​常见数据结构​​:​​B+Tree​​(最常用)、Hash。
  3. ​什么是内连接、左连接、右连接?​

    • ​内连接(INNER JOIN)​​:返回两个表中连接字段匹配的行。
    • ​左连接(LEFT JOIN)​​:返回左表的所有行,即使右表中没有匹配的行。右表无匹配则为NULL。
    • ​右连接(RIGHT JOIN)​​:返回右表的所有行,即使左表中没有匹配的行。左表无匹配则为NULL。

​六、Spring 框架​

  1. ​Spring 中 Bean 的作用域有哪些?​

    • ​singleton​​(默认):单例,一个Spring容器中只有一个Bean实例。
    • ​prototype​​:原型,每次请求(获取)都会创建一个新的Bean实例。
    • ​request​​:一次HTTP请求一个实例。
    • ​session​​:一个HTTP Session一个实例。
    • ​application​​:一个ServletContext生命周期一个实例。
  2. ​Spring 事务的实现原理是什么?事务传播行为有哪些?​

    • ​原理​​:基于AOP(面向切面编程),通过动态代理和​​事务管理器​​(如DataSourceTransactionManager)来实现。在方法调用前开启事务,方法执行后提交或回滚事务。

    • ​传播行为​​(常用):

      • ​REQUIRED​​(默认):如果当前没有事务,就新建一个事务;如果已存在一个事务,就加入到这个事务中。
      • ​REQUIRES_NEW​​:新建事务,如果当前存在事务,则把当前事务挂起。
      • ​SUPPORTS​​:支持当前事务,如果当前没有事务,就以非事务方式执行。
  3. ​Spring MVC 的工作流程是什么?​

    1. 用户发送请求至​​前端控制器(DispatcherServlet)​​。
    2. DispatcherServlet收到请求调用​​处理器映射器(HandlerMapping)​​。
    3. HandlerMapping找到具体的处理器,返回给DispatcherServlet。
    4. DispatcherServlet调用​​处理器适配器(HandlerAdapter)​​。
    5. HandlerAdapter经过适配调用具体的​​控制器(Controller)​​。
    6. Controller执行完成返回一个​​ModelAndView​​。
    7. HandlerAdapter将ModelAndView返回给DispatcherServlet。
    8. DispatcherServlet将ModelAndView传给​​视图解析器(ViewResolver)​​。
    9. ViewResolver解析后返回具体的​​View​​。
    10. DispatcherServlet根据View进行渲染视图,并返回给客户端。

​七、综合与场景题​

  1. ​你在项目中遇到过什么印象最深的技术难题?你是怎么解决的?​

    • ​考察点​​:解决问题的能力、经验总结、技术深度。
    • ​回答建议​​:准备一个真实案例,使用​​STAR原则​​(Situation, Task, Action, Result)来描述。例如:遇到了一个线上CPU飙高的问题,通过topjstack等命令排查,发现是死循环导致的,最终修复了代码逻辑。
  2. ​如果线上接口突然变慢,你会如何排查?​

    • 检查应用服务器监控(CPU、内存、磁盘IO、网络IO)。
    • 查看应用日志,是否有大量报错(如数据库连接超时、第三方接口超时)。
    • 排查数据库(慢查询SQL、是否锁表)。
    • 排查中间件(Redis连接池、MQ堆积)。
    • 使用链路追踪工具(如Skywalking)分析调用链耗时。
  3. ​谈谈你对微服务的理解,它有什么优缺点?​

    • ​优点​​:服务解耦、独立开发部署、技术选型灵活、容错性高。
    • ​缺点​​:架构复杂、运维要求高、部署复杂、分布式事务问题、测试难度大、通信成本高。