无题

1. Java基础

1. 谈谈你对AQS的理解

  1. AQS是多线程同步器,它是J.U.C包中多个组件的底层实现,如Lock、CountDownLatch、Semaphore等都用到了AQS.

  2. 从本质上来说,AQS提供了两种锁机制,分别是排它锁,和 共享锁。

  3. 排它锁,就是存在多线程竞争同一共享资源时,同一时刻只允许一个线程访问该共享资源,也就是多个线程中只能有一个线程获得锁资源,比如Lock中的ReentrantLock重入锁实现就是用到了AQS中的排它锁功能。

  4. 共享锁也称为读锁,就是在同一时刻允许多个线程同时获得锁资源,比如CountDownLatch和Semaphore都是用到了AQS中的共享锁功能。

2. 你能说一下什么是受检异常和非受检异常吗?

  1. 在 Java 中,异常主要分为受检异常和非受检异常。

  2. 受检异常是指继承自 Exception,但不继承 RuntimeException 的异常。编译器会强制检查,必须通过 try-catch 捕获或者 throws 抛出,这类异常一般是业务可预期、可恢复的异常,比如 IOException、SQLException 等。

  3. 非受检异常包括 RuntimeException 和 Error。编译器不强制处理,通常是代码逻辑问题或者 JVM 层面的严重错误,比如 NullPointerException、IndexOutOfBoundsException,还有 OOM、栈溢出这类 Error。

  4. 简单来说,受检异常是编译期必须处理的,非受检异常是运行时才会出现的问题。我回答完毕,谢谢面试官。

3. 请说一下对象的创建过程

面试官您好,Java 对象创建过程我是这样理解的:

  1. 首先 JVM 会检查这个类有没有被加载过,如果没有,就先进行类加载。
  2. 然后在堆内存中为对象分配内存空间。
  3. 接着给对象的成员变量默认初始化,比如 int 变成 0,引用变成 null。
  4. 再执行我们代码里写的显式赋值和构造方法,给对象赋上真正的初始值。
  5. 最后把对象地址赋值给引用变量,对象就创建完成了。

4. 简单说一下你对序列化和反序列化的理解

序列化和反序列化是 Java 中用于处理对象 “跨存储 / 跨网络传输” 的核心机制:

  1. 序列化:把内存中的 Java 对象,转换成字节序列(二进制数据)的过程。比如把一个 User 对象转成字节流,方便存到文件里、或者通过网络传给另一台服务器。要实现序列化,只需要让类实现Serializable标记接口就行。
  2. 反序列化:和序列化相反,是把字节序列重新转换成内存中可用的 Java 对象的过程。比如从文件里读出之前存的字节数据,还原成原来的 User 对象,能直接调用对象的方法、获取属性。

举个通俗的例子:序列化就像把行李箱(对象)打包成快递包裹(字节序列),方便运输;反序列化就是收到包裹后,拆开还原成原来的行李箱。

5. String、StringBuffer、StringBuilder区别

String、StringBuffer、StringBuilder 最主要就两点区别:能不能改、线程安不安全。

  • String 是不可变的,每次拼接、修改,其实都是新建一个字符串,频繁修改会很慢、很占内存。
  • StringBuilder 是可变的,修改直接在原对象上改,效率最高,但线程不安全,单线程用它最多。
  • StringBuffer 也是可变的,效率比 StringBuilder 慢一点,但它加了锁,线程安全,适合多线程环境。