一、基础概念

1. JDK、JRE、JVM 的区别与联系?

  • JVM(Java虚拟机):运行Java字节码的虚拟计算机,是Java跨平台的核心。
  • JRE(Java运行环境):包含JVM和核心类库,用于运行Java程序,不包含开发工具。
  • JDK(Java开发工具包):包含JRE + 开发工具(如javac编译器、jar打包工具等)。
  • 联系:JDK ⊇ JRE ⊇ JVM,开发时用JDK,运行时只需JRE。

2. Java是编译型还是解释型语言?

Java是编译与解释并存的语言:

  • 先由javac将.java源文件编译为.class字节码文件(编译)。
  • 再由JVM对字节码进行解释执行或通过JIT即时编译器编译为本地机器码执行(解释+编译)。

3. 面向对象三大特性(封装、继承、多态)的理解?

  • 封装:将数据和操作封装在类中,隐藏内部实现细节,只暴露必要的接口。通过访问修饰符(private, protected, public)实现。
  • 继承:子类可继承父类的属性和方法,实现代码复用。Java是单继承,但可通过接口实现多继承效果。
  • 多态:同一行为的不同表现形式,分为编译时多态(方法重载)和运行时多态(方法重写)。运行时多态依赖继承、重写、父类引用指向子类对象。

4. 抽象类与接口的区别(JDK8+)?

对比项抽象类接口
实例化不能不能
构造方法有无
方法实现可以有具体方法JDK8起支持default和static方法
成员变量无限制只能是public static final常量
继承关系单继承可多实现(多继承)
设计理念is-a 关系,模板式设计has-a / can-do 关系,行为契约

5. == 和 equals() 的区别?

  • ==:基础类型比较值,引用类型比较内存地址。
  • equals():Object类中默认用==比较地址,但String、Integer等重写了equals(),转而比较内容。
  • 重点:重写equals()必须重写hashCode(),否则在HashSet、HashMap中会出现逻辑错误。

6. final 关键字的作用?

  • 修饰类:类不能被继承(如String类)。
  • 修饰方法:方法不能被重写。
  • 修饰变量:变量成为常量,基础类型值不可变,引用类型地址不可变但内容可变。

7. String、StringBuilder、StringBuffer 的区别?

  • String:不可变类,每次修改都生成新对象,线程安全(因不可变)。
  • StringBuffer:可变类,线程安全(方法用synchronized修饰),效率较低。
  • StringBuilder:可变类,线程不安全,单线程下性能最优。

二、异常处理

8. Java 异常体系是怎样的?

Throwable
├── Error(严重问题,不建议处理,如OutOfMemoryError)
└── Exception
    ├── RuntimeException(运行时异常/非受检异常,如NullPointerException)
    └── 非RuntimeException(编译时异常/受检异常,如IOException)

9. finally 块一定会执行吗?final、finally、finalize 的区别?

  • finally:通常都会执行,除非在try/catch中调用了System.exit(0)或JVM崩溃。
  • final:关键字,修饰类、方法、变量。
  • finally:异常处理中保证代码执行的块。
  • finalize:Object类的方法,对象被GC回收前调用,JDK9已废弃,不推荐使用。

三、集合框架

10. ArrayList 和 LinkedList 的区别?

对比项ArrayListLinkedList
底层结构动态数组双向链表
随机访问快 O(1)慢 O(n)
增删(非尾部)慢(需移动元素) O(n)快(只需修改指针) O(1)
内存占用相对小(只存数据)相对大(存数据+前后指针)
适用场景频繁读取、尾部插入频繁头尾插入删除

11. HashMap 的底层原理(JDK8)?

  • 数据结构:数组 + 链表 + 红黑树。
  • 存储过程:
    1. 通过hashCode()计算哈希值,再通过(n-1) & hash确定桶下标。
    2. 该桶为空,直接存入。
    3. 不为空,判断key是否相等(equals),相等则覆盖。
    4. 不相等则以链表形式插入。
    5. 链表长度≥8且数组长度≥64时,链表转为红黑树,提升搜索效率。
  • 扩容机制:默认容量16,负载因子0.75,超过阈值时扩容为原来的2倍。
  • 为什么线程不安全:并发put可能导致数据丢失(覆盖)、链表成环(JDK7头插法)、size计数不准。

12. HashMap 与 Hashtable、ConcurrentHashMap 的区别?

对比项HashMapHashtableConcurrentHashMap
线程安全否是(synchronized方法)是(分段锁/CAS+synchronized)
效率高低(全表锁)高(细粒度锁)
null键值允许一个null键不允许不允许
JDK版本1.21.0(已不推荐)1.5

13. List、Set、Map 三者的区别?

  • List:有序(存入顺序),可重复,按索引访问。
  • Set:无序(部分如LinkedHashSet有序),不可重复,底层多为Map实现。
  • Map:键值对存储,key不可重复,value可重复。

四、多线程与并发

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

  1. 继承Thread类,重写run()方法。
  2. 实现Runnable接口,作为参数传入Thread。
  3. 实现Callable接口 + FutureTask(有返回值,可抛异常)。
  4. 通过线程池(Executors框架)创建(推荐)。

15. synchronized 关键字的用法与锁升级?

  • 修饰对象:
    • 修饰实例方法:锁是当前对象实例this。
    • 修饰静态方法:锁是当前类的Class对象。
    • 修饰代码块:锁是括号里指定的对象。
  • 锁升级(JDK6后优化):偏向锁 → 轻量级锁(CAS自旋) → 重量级锁(操作系统互斥量),随竞争程度逐渐膨胀。

16. volatile 关键字的作用?

  • 保证可见性:一个线程修改了变量,其他线程立即可见(强制读写主内存,禁止线程工作内存缓存)。
  • 禁止指令重排序:通过内存屏障防止JVM对指令的乱序执行优化。
  • 不保证原子性:如i++这种复合操作不具备原子性。

17. wait() 和 sleep() 的区别?

对比项wait()sleep()
所属类Object类Thread类
锁释放调用后释放锁调用后不释放锁
唤醒条件需notify()/notifyAll()唤醒,或设置超时时间到自动唤醒
使用位置必须在synchronized块中任意位置

18. 线程池的核心参数与拒绝策略?

  • 七大核心参数(ThreadPoolExecutor):
    1. corePoolSize 核心线程数
    2. maximumPoolSize 最大线程数
    3. keepAliveTime 空闲存活时间
    4. unit 时间单位
    5. workQueue 工作队列(有界/无界)
    6. threadFactory 线程工厂
    7. handler 拒绝策略
  • 四种拒绝策略:
    • AbortPolicy:抛异常(默认)
    • CallerRunsPolicy:由调用线程执行任务
    • DiscardOldestPolicy:丢弃队列最早任务
    • DiscardPolicy:静默丢弃新任务

五、JVM 基础

19. JVM 内存模型(运行时数据区)包含哪些部分?

  1. 程序计数器:线程私有,记录当前线程执行字节码的行号。
  2. 虚拟机栈:线程私有,由栈帧组成,每个方法执行时创建栈帧,存放局部变量表等。
  3. 本地方法栈:为Native方法服务。
  4. 堆:所有线程共享,存放对象实例,GC的主要区域。
  5. 方法区(元空间):存储类信息、常量、静态变量、即时编译后的代码。JDK8后用本地内存的元空间替代永久代。

20. 常见垃圾回收算法?

  1. 标记-清除:标记存活对象,清除未标记对象。产生内存碎片。
  2. 标记-复制:将内存分为两块,存活对象复制到另一块,整体清除当前块。无碎片但浪费空间(新生代使用)。
  3. 标记-整理:标记后,存活对象向一端移动,清理边界外内存。无碎片,代价较高(老年代使用)。
  4. 分代收集:新生代用复制算法,老年代用标记-清除/整理算法。

六、进阶特性(JDK8+)

21. Lambda 表达式与函数式接口?

  • 函数式接口:只有一个抽象方法的接口,可用@FunctionalInterface注解标识。
  • Lambda表达式:用于简化匿名内部类的写法,本质是函数式接口的实现。

22. Stream 流的常用操作?

操作类型常用API
中间操作(惰性求值)filter, map, sorted, distinct, limit
终端操作(触发计算)collect, forEach, reduce, count, anyMatch

23. Optional 类的作用?

解决NullPointerException问题,作为可能为null的值的容器,强制要求使用者显式处理null情况。常用方法:ofNullable(), orElse(), ifPresent()。


七、编码实践

24. Comparable 和 Comparator 的区别?

  • Comparable:内部比较器,类自身实现compareTo方法,定义自然排序规则。
  • Comparator:外部比较器,不修改类本身,可定义多个排序规则。使用时作为参数传入sort方法。

25. 深拷贝与浅拷贝的区别?

  • 浅拷贝:复制对象时,基础类型复制值,引用类型复制引用地址(指向同一对象)。
  • 深拷贝:复制对象时,引用类型也会创建新对象并复制内容,两者完全独立。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐