Java常考十道面试题
2026/6/11 9:48:10 网站建设 项目流程

1. Java 的三大特性是什么?请分别说明。

答案

1. 封装(Encapsulation)

  • 定义:隐藏对象内部实现细节,通过private限制访问,提供getter/setter等公共方法交互

  • 作用:降低耦合、提高安全性、便于维护

  • 示例:实体类的属性封装

2. 继承(Inheritance)

  • 定义:子类通过extends继承父类非私有属性和方法,实现代码复用

  • 特点:Java 只支持单继承(避免菱形依赖),可通过接口间接实现多继承

  • 作用:代码复用、扩展功能

3. 多态(Polymorphism)

  • 定义:同一行为的不同表现形式

  • 核心:方法重写(子类覆写父类方法)和向上转型(父类引用指向子类对象)

  • 示例List list = new ArrayList<>(),调用list.add()时实际执行 ArrayList 的实现

  • 作用:提高代码灵活性和可扩展性


2. String、StringBuffer、StringBuilder 的区别是什么?

答案

特性

String

StringBuffer

StringBuilder

可变性

不可变(final 修饰字符数组)

可变(数组扩容)

可变(数组扩容)

线程安全

安全(无修改操作)

安全(方法加synchronized

不安全(无锁)

效率

最低(修改会创建新对象)

中等

最高

适用场景

少量字符串操作

多线程环境字符串拼接

单线程环境字符串拼接

核心区别

  • String:不可变对象,每次修改都会创建新对象,适合常量定义

  • StringBuffer:线程安全的可变字符串,适合多线程环境

  • StringBuilder:非线程安全的可变字符串,效率最高,适合单线程环境


3. JVM 内存模型包含哪些主要分区?各有什么作用?

答案

JVM 内存模型(JMM)定义了线程如何通过内存交互,解决多线程可见性、原子性、有序性问题。

核心分区:

  1. 程序计数器(Program Counter)

    • 线程私有,记录当前线程执行的字节码行号

    • 无 OOM 可能

  2. 虚拟机栈(JVM Stack)

    • 线程私有,存储方法调用的栈帧(局部变量、操作数栈等)

    • 栈深度溢出抛StackOverflowError,扩容失败抛OutOfMemoryError

  3. 本地方法栈(Native Method Stack)

    • 线程私有,为 Native 方法(如System.currentTimeMillis())提供内存支持

    • 可能抛StackOverflowError/OOM

  4. 堆(Heap)

    • 线程共享,存储对象实例和数组

    • GC 主要区域,分年轻代、老年代

    • OOM 高频发生区

  5. 方法区(Method Area)

    • 线程共享,存储类信息、常量、静态变量等

    • JDK 8 后用元空间(Metaspace)实现,占用本地内存,默认无上限


4. 什么是 GC(垃圾回收)?常见 GC 算法和收集器有哪些?

答案

GC 定义

自动回收堆中"不可达对象"(无引用指向的对象)的内存,避免内存泄漏,无需手动释放。

核心算法:

  1. 标记-清除(Mark-Sweep)

    • 先标记垃圾,再清除

    • 缺点:效率低、会产生内存碎片

  2. 复制算法(Copying)

    • 将内存分为两块,存活对象复制到另一块,清除原块

    • 优点:无碎片、效率高

    • 适用:年轻代默认使用

  3. 标记-整理(Mark-Compact)

    • 标记后将存活对象向一端移动,再清除剩余区域

    • 适用:老年代默认使用

常见收集器:

年轻代

  • SerialGC:串行,单线程

  • Parallel Scavenge:并行,注重吞吐量

老年代

  • Serial Old:串行

  • Parallel Old:并行

  • CMS:并发,注重响应时间

  • G1:区域分代,兼顾吞吐量和响应时间


5. Java 中实现多线程的三种方式及区别是什么?

答案

方式 1:继承 Thread 类

class MyThread extends Thread { @Override public void run() { // 线程执行代码 } } // 启动:new MyThread().start();
  • 缺点:单继承限制,无法继承其他类

方式 2:实现 Runnable 接口

class MyRunnable implements Runnable { @Override public void run() { // 线程执行代码 } } // 启动:new Thread(new MyRunnable()).start();
  • 优点:无继承限制,可实现多个接口

  • 缺点:无法直接获取返回值

方式 3:实现 Callable 接口

class MyCallable implements Callable<String> { @Override public String call() throws Exception { // 线程执行代码,可返回值 return "result"; } } // 启动:FutureTask<String> task = new FutureTask<>(new MyCallable()); // new Thread(task).start();
  • 优点:支持返回值和异常处理,适合异步任务

  • 缺点:代码稍复杂


6. 什么是线程安全?如何保证线程安全?

答案

线程安全定义

多线程并发访问共享资源时,不会出现数据错乱、死锁等问题(比如多线程抢票,不会出现超卖、重复售票)。

实现方式:

  1. 锁机制

    • synchronized:关键字,可修饰方法/代码块,底层是监视器锁

    • ReentrantLock:类锁,支持公平锁/非公平锁、可中断

  2. 无锁机制

    • volatile:修饰变量,保证可见性和有序性,不保证原子性

    • 原子类(AtomicInteger):基于 CAS 实现原子操作

  3. 线程封闭

    • 局部变量:线程私有,无共享

    • ThreadLocal:每个线程独立存储副本,避免共享

  4. 并发容器

    • ConcurrentHashMap:分段锁/CAS 实现线程安全

    • CopyOnWriteArrayList:写时复制,读无锁


7. HashMap 和 ConcurrentHashMap 的区别是什么?(JDK 8+)

答案

特性

HashMap

ConcurrentHashMap

线程安全

不安全

安全(CAS + synchronized)

null 键/值

允许

不允许 null 键,允许 null 值

迭代器

Fail-Fast

Weakly Consistent

锁粒度

无锁

桶级别锁(JDK 8+)

性能

单线程性能高

并发性能高

ConcurrentHashMap JDK 8+ 改进:

  • JDK 7:分段锁(Segment),默认 16 个段

  • JDK 8+:CAS + synchronized,锁粒度更细(桶级别)

  • 结构:数组 + 链表 + 红黑树,链表长度 > 8 转为红黑树


8. == 和 equals 的区别是什么?

答案

== 运算符

  • 基本数据类型:比较值是否相同

  • 引用数据类型:比较引用地址是否相同

equals 方法

  • 默认实现:与==相同,比较引用地址

  • 重写后:比较对象内容(如 String、Integer 等类重写了 equals)

示例:

String x = "string"; String y = "string"; String z = new String("string"); System.out.println(x == y); // true(同一引用) System.out.println(x == z); // false(不同引用) System.out.println(x.equals(y)); // true(内容相同) System.out.println(x.equals(z)); // true(内容相同)

注意事项:

  • null值不能调用equals()方法,否则会抛出空指针异常

  • 重写equals()必须重写hashCode()


9. int 和 Integer 的区别是什么?

答案

特性

int

Integer

类型

基本数据类型

包装类(引用类型)

存储位置

栈内存

堆内存

默认值

0

null

是否可为 null

泛型支持

不支持

支持

方法

提供丰富方法(如 parseInt、toString)

装箱与拆箱:

  • 装箱Integer a = 10;(自动将 int 转换为 Integer)

  • 拆箱int b = a;(自动将 Integer 转换为 int)

缓存机制:

Integer 缓存了 -128 到 127 的值,在这个范围内使用==比较返回 true。


10. ArrayList 和 LinkedList 的区别是什么?

答案

特性

ArrayList

LinkedList

底层实现

动态数组

双向链表

随机访问

O(1),效率高

O(n),效率低

插入/删除

需要移动元素,效率较低

只需修改指针,效率高

内存占用

初始容量 10,扩容 1.5 倍

每个元素存储前驱后继指针

线程安全

不安全

不安全

适用场景:

  • ArrayList:适合增删操作较少、查询操作较多的场景

  • LinkedList:适合查询操作较少、增删操作较多的场景

扩容机制:

  • ArrayList:初始容量为 10,扩容为原来的 1.5 倍

  • LinkedList:无需扩容,动态添加节点

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询