Java八股:面试高频50

一、基础语法

1. Java的三大特性是什么?分别简单解释其含义

核心结论 :Java三大特性为封装、继承、多态,是面向对象编程的核心基础。

  • 封装 :将对象的属性和行为包装为类,隐藏内部实现细节,仅对外暴露公共访问接口,保证数据安全、降低耦合。
  • 继承 :子类复用父类的属性和方法,并可扩展自身功能,减少代码冗余,体现类的层级关系。
  • 多态:同一行为在不同子类中表现出不同形态,基于继承/接口实现,提升代码扩展性和灵活性。

2. Java中基本数据类型有哪些?对应的包装类分别是什么

Java有8种基本数据类型,均有对应包装类(包装类是引用类型,提供方法和泛型支持):

基本数据类型 包装类 取值范围
byte Byte -128 ~ 127
short Short -32768 ~ 32767
int Integer -231 ~ 231-1
long Long -263 ~ 263-1
float Float 单精度浮点
double Double 双精度浮点
char Character 0 ~ 65535(Unicode)
boolean Boolean true/false

3. int和Integer的区别是什么?自动装箱和自动拆箱的原理

核心区别
  1. 类型 :int是基本数据类型 ,Integer是int的包装类(引用类型)
  2. 存储 :int直接存数值 ,Integer存对象引用,需分配堆内存;
  3. 默认值 :int默认0 ,Integer默认null
  4. 使用场景 :int用于普通数值计算,Integer用于泛型、集合、反射等场景。
自动装箱/拆箱原理
  • 自动装箱 :基本类型→包装类(如Integer a = 10),底层调用Integer.valueOf(10)
  • 自动拆箱 :包装类→基本类型(如int b = a),底层调用a.intValue()
  • 目的:简化基本类型与包装类的转换,无需手动调用方法。

4. String、StringBuffer、StringBuilder的区别?适用场景

特性 String StringBuffer StringBuilder
底层实现 final修饰的char数组 char数组 char数组
可变性 不可变(修改即创建新对象) 可变 可变
线程安全 安全(不可变) 安全(synchronized) 不安全
性能 低(频繁修改耗内存)
适用场景
  • String:字符串不修改、少量修改(如常量、配置);
  • StringBuffer:多线程环境下频繁修改字符串
  • StringBuilder:单线程环境下频繁修改字符串(优先使用)。

5. Java中==和equals()的区别?重写equals()时为什么要重写hashCode()

==和equals()区别
  1. ==
    • 基本类型:比较数值是否相等
    • 引用类型:比较内存地址是否相同(是否为同一对象)。
  2. equals()
    • 未重写:和==一样,比较内存地址;
    • 重写(如String、Integer):比较对象内容是否相等
重写equals必须重写hashCode的原因
  • 规范:两个对象equals相等,hashCode必须相等
  • 场景:HashMap/HashSet通过hashCode定位存储位置,若只重写equals不重写hashCode,会导致相同内容的对象被存为多个,破坏集合唯一性。

6. final关键字可以修饰哪些内容?分别有什么作用

final表示不可改变 ,可修饰类、方法、变量

  1. 修饰类 :类不能被继承(如String、Integer),无子类;
  2. 修饰方法 :方法不能被重写,保证方法逻辑不被修改;
  3. 修饰变量
    • 基本变量:数值初始化后不可修改
    • 引用变量:引用地址不可变,对象内部属性可修改。

7. static关键字的作用?static方法和非static方法的区别

static核心作用

表示静态 ,属于类本身,不属于单个对象,随类加载而加载。

  1. 修饰变量:静态变量,所有对象共享一份内存;
  2. 修饰方法:静态方法,无需创建对象可直接调用;
  3. 修饰代码块:静态代码块,类加载时执行一次,用于初始化静态资源。
static方法 / 非static方法
特性 静态方法 非静态方法
归属 对象
调用方式 类名.方法名 对象.方法名
访问权限 只能访问静态成员 可访问静态+非静态成员
this/super 不能使用 可以使用

8. Java中的注释有哪几种?分别是什么

  1. 单行注释// 注释内容,用于简短说明;
  2. 多行注释/* 注释内容 */,用于多行说明;
  3. 文档注释/** 注释内容 */,可生成API文档,包含参数、返回值说明。

9. break、continue、return的区别

  1. break跳出当前循环/switch,终止整个循环结构;
  2. continue跳过本次循环剩余代码,直接进入下一次循环;
  3. return结束当前方法,返回结果(无返回值则直接退出方法)。

10. if-else和switch-case的区别?switch-case支持哪些数据类型

核心区别
  • if-else:可判断区间、逻辑表达式 (如a>10 && a<20),适用所有判断场景;
  • switch-case:仅判断固定值,结构清晰,效率略高。
switch支持类型
  • 基本类型:byte、short、char、int;
  • 包装类:Byte、Short、Character、Integer;
  • 枚举:Enum;
  • JDK7+:String
  • 不支持long、float、double、boolean

11. 数组和集合的区别?数组的长度是固定的吗

核心区别
特性 数组 集合
长度 固定,创建后不可改 可变,动态扩容
存储类型 基本类型+引用类型 引用类型(泛型)
功能 简单存储、遍历 提供增删改查、排序等方法
泛型支持 有,类型安全
数组长度

数组长度固定,创建时指定长度,无法直接扩容,需新建数组复制元素。

12. Java中异常的分类?Error和Exception的区别

异常分类

Throwable是顶级父类,分为ErrorException

  1. Error :JVM级错误(如OOM、StackOverflowError),无法通过代码处理,只能避免;
  2. Exception :程序级异常,可通过try-catch处理,分为:
    • 编译时异常(受检):IOException、SQLException,编译期必须处理;
    • 运行时异常(非受检):NullPointerException、IndexOutOfBoundsException,运行时触发。
Error / Exception
  • Error :JVM无法恢复的严重错误,无需捕获
  • Exception :程序逻辑问题,可捕获处理,保证程序正常运行。

13. try-catch-finally的执行顺序?finally块一定会执行吗

执行顺序
  1. 先执行try块,无异常直接执行finally;
  2. 有异常:执行catch块,再执行finally;
  3. finally最后执行,用于释放资源(如流、连接)。
finally不一定执行的场景
  1. JVM提前终止(如System.exit(0));
  2. 线程被中断/杀死;
  3. try块中无限循环,未执行到finally。

二、面向对象

1. 什么是面向对象?面向对象和面向过程的区别

  • 面向对象(OOP) :以对象为核心,将数据和行为封装为类,通过对象交互实现功能。
  • 面向过程(POP) :以过程/步骤为核心,按步骤编写函数,一步步执行。
核心区别
特性 面向过程 面向对象
核心 步骤/函数 对象/类
耦合度
扩展性
适用场景 简单、固定逻辑 复杂、多变业务

2. 封装的意义是什么?如何实现封装

封装意义
  1. 隐藏实现细节,外部无法直接访问内部数据;
  2. 保证数据安全,通过公共方法控制数据访问;
  3. 降低耦合,内部修改不影响外部调用。
实现方式
  1. private修饰类的属性;
  2. 提供public的get/set方法,对外暴露属性访问入口;
  3. 在get/set中添加数据校验逻辑。

3. 继承的好处是什么?Java支持多继承吗?为什么

继承好处
  1. 代码复用,子类直接使用父类属性和方法;
  2. 扩展功能,子类可重写父类方法,新增自身逻辑;
  3. 体现层级关系,符合现实世界逻辑。
Java不支持多继承
  • 原因:避免菱形继承问题(多个父类有同名方法,子类无法确定调用哪个);
  • 替代方案:接口多实现,接口无方法实现,无冲突。

4. 多态的实现条件是什么?静态多态和动态多态的区别

多态实现条件
  1. 存在继承/实现关系;
  2. 子类重写父类/接口方法;
  3. 父类引用指向子类对象(向上转型)。
静态vs动态多态
  • 静态多态(编译期)方法重载,编译期确定调用方法,根据参数列表区分;
  • 动态多态(运行期)方法重写,运行期根据对象实际类型确定调用方法。

5. 抽象类和接口的区别?使用场景

特性 抽象类(abstract class) 接口(interface)
继承/实现 单继承 多实现
方法实现 可包含抽象+非抽象方法 JDK8+:抽象+默认+静态方法
成员变量 任意类型 默认为public static final
构造方法
使用场景
  • 抽象类:多个类有共同属性和行为,需要复用代码;
  • 接口:定义规范/契约,不关心实现,多个类可实现同一规范。

6. 重写(Override)和重载(Overload)的区别

特性 重写(Override) 重载(Overload)
位置 父子类/接口实现类 同一个类
方法名 相同 相同
参数列表 相同 不同(个数/类型/顺序)
返回值 相同或子类 无关
修饰符 不能更严格 无关
时期 运行期(动态) 编译期(静态)

7. this和super的区别

  1. this
    • 指向当前对象,访问当前类的属性、方法、构造方法;
    • 调用本类构造:this(参数),必须在构造方法第一行。
  2. super
    • 指向父类对象,访问父类的属性、方法、构造方法;
    • 调用父类构造:super(参数),必须在子类构造第一行。

8. 构造方法的特点?构造方法可以重载吗?可以重写吗

构造方法特点
  1. 方法名与类名完全相同
  2. 无返回值,不写void;
  3. 创建对象时自动执行,用于初始化对象;
  4. 无参构造默认存在,定义有参构造后默认无参构造消失。
重载/重写
  • 可以重载:多个构造方法,参数列表不同;
  • 不能重写:构造方法属于类,子类无法继承,无法重写。

9. 什么是内部类?内部类有哪几种?各自特点

内部类:定义在类内部的类,可访问外部类私有成员,增强封装。

  1. 成员内部类:类内方法外,无static,可访问外部类所有成员;
  2. 静态内部类:static修饰,仅访问外部类静态成员;
  3. 局部内部类:方法内,作用域仅限当前方法;
  4. 匿名内部类:无类名,一次性使用,简化接口/抽象类实现。

10. 什么是单例模式?懒汉式、饿汉式实现+优缺点

单例模式:保证一个类只有一个实例,提供全局访问点,适用于配置类、线程池。

1. 饿汉式(立即加载)
java 复制代码
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() { return INSTANCE; }
}
  • 优点:线程安全、实现简单、无锁效率高;
  • 缺点:类加载即创建,浪费内存(不用也创建)。
2. 懒汉式(延迟加载)
java 复制代码
public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (instance == null) instance = new Singleton();
        return instance;
    }
}
  • 优点:延迟加载,用到才创建,节省内存;
  • 缺点:synchronized加锁,多线程效率低

三、集合框架

1. Java集合框架整体结构?Collection和Map的区别

整体结构
  • 单列集合:Collection(List、Set、Queue);
  • 双列集合:Map(HashMap、TreeMap、ConcurrentHashMap)。
Collection vs Map
  • Collection:存储单个对象,有序/无序、可重复/不可重复;
  • Map:存储键值对(Key-Value),Key唯一,Value可重复。

2. ArrayList和LinkedList的区别?底层实现

特性 ArrayList LinkedList
底层实现 动态数组 双向链表
访问效率 (随机访问) 低(遍历查找)
增删效率 末尾快,中间慢 首尾快,中间慢
内存占用 连续内存,占用少 节点存数据+地址,占用多
线程安全 不安全 不安全
适用场景
  • ArrayList:频繁查询、少量增删
  • LinkedList:频繁首尾增删、少量查询

3. HashMap底层实现原理?JDK1.7和1.8的区别

底层原理
  • 数据结构:数组+链表+红黑树(JDK1.8);
  • 存储:通过Key的hashCode计算数组下标,冲突则用链表/红黑树存储;
  • 扩容:负载因子0.75,容量达到阈值=容量*0.75时扩容为2倍。
JDK1.7 vs 1.8
特性 JDK1.7 JDK1.8
结构 数组+链表 数组+链表+红黑树
链表插入 头插法 尾插法
树化条件 链表长度≥8且数组长度≥64
扩容效率 低(rehash易死链) 高(优化rehash)

4. HashSet底层实现?如何保证元素不重复

  • 底层:基于HashMap实现,元素存为HashMap的Key,Value固定为Object;
  • 去重原理:
    1. 先比较hashCode,不同则直接存储;
    2. hashCode相同,再用equals比较,不同则存储,相同则覆盖。

5. TreeMap和HashMap的区别?TreeMap排序规则

特性 TreeMap HashMap
底层 红黑树 数组+链表+红黑树
有序性 Key有序 无序
线程安全 不安全 不安全
性能 增删改查O(logn) 平均O(1),最差O(logn)
TreeMap排序规则
  1. 自然排序:Key实现Comparable接口,重写compareTo;
  2. 定制排序:创建TreeMap时传入Comparator比较器。

6. ConcurrentHashMap底层实现?线程安全吗?HashMap/HashTable

底层实现
  • JDK1.7:分段锁(Segment),每段独立加锁,并发高;
  • JDK1.8:CAS+synchronized,锁粒度为数组节点,效率更高。
线程安全

通过锁分段/CAS+synchronized保证线程安全,支持高并发。

三者区别
特性 HashMap HashTable ConcurrentHashMap
线程安全 不安全 安全(全表synchronized) 安全(高并发)
效率 中高
Key/Value 允许null 不允许null 不允许null

7. 集合遍历方式有哪些?迭代器(Iterator)特点

遍历方式
  1. 普通for循环:通过索引遍历,适用于List;
  2. 增强for循环:简化遍历,底层是Iterator;
  3. 迭代器Iterator:通用遍历方式,支持遍历中删除;
  4. Lambda表达式:JDK8+,简洁高效。
Iterator特点
  1. 通用遍历接口,所有Collection集合都支持;
  2. fail-fast机制:遍历中集合被修改,抛出ConcurrentModificationException;
  3. 仅支持单向遍历,安全删除元素。

四、IO流与异常

1. Java IO流分类?字节流和字符流的区别

IO分类
  1. 按数据单位:字节流 (8位)、字符流(16位);
  2. 按流向:输入流、输出流;
  3. 按功能:节点流、处理流(缓冲流、转换流)。
字节流vs字符流
特性 字节流(InputStream/OutputStream) 字符流(Reader/Writer)
处理数据 所有文件(图片、视频、文本) 纯文本文件
编码 不处理编码 自动处理Unicode编码
常用类 FileInputStream、FileOutputStream FileReader、FileWriter

2. 常用IO流实现类

  1. 字节节点流:FileInputStream、FileOutputStream;
  2. 字符节点流:FileReader、FileWriter;
  3. 缓冲流:BufferedInputStream、BufferedReader、BufferedWriter;
  4. 转换流:InputStreamReader、OutputStreamWriter(字节→字符);
  5. 对象流:ObjectInputStream、ObjectOutputStream(序列化)。

3. 缓冲流作用?原理

作用

提升IO效率,减少磁盘读写次数。

原理
  • 内部维护缓冲区数组,先将数据读入缓冲区,满了再一次性写入磁盘;
  • 避免逐字节读写,大幅提升性能。

4. 异常处理方式?throw和throws区别

异常处理方式
  1. try-catch-finally:捕获并处理异常,程序继续运行;
  2. throws:声明异常,将异常抛给上层调用者处理;
  3. throw:手动抛出异常对象。
throw vs throws
特性 throw throws
位置 方法体内 方法声明后
内容 抛出异常对象 声明异常类型
次数 抛出一个 可声明多个
作用 手动触发异常 通知调用者处理异常

5. 自定义异常实现方式?为什么要自定义

实现方式
  1. 继承Exception (编译时异常)或RuntimeException(运行时异常);
  2. 提供无参/有参构造方法,调用父类构造。
java 复制代码
public class MyException extends RuntimeException {
    public MyException(String message) { super(message); }
}
自定义原因
  1. 区分业务异常和系统异常,语义清晰;
  2. 统一异常处理,便于定位问题;
  3. 自定义异常信息,更贴合业务。

五、多线程

1. Java创建线程的三种方式+步骤+优缺点

  1. 继承Thread类
    • 步骤:继承Thread→重写run()→new对象→start()启动;
    • 优点:简单;缺点:单继承限制,无法继承其他类。
  2. 实现Runnable接口
    • 步骤:实现Runnable→重写run()→new Thread(任务)→start();
    • 优点:避免单继承,资源共享;缺点:无返回值。
  3. 实现Callable接口
    • 步骤:实现Callable→重写call()→FutureTask包装→new Thread→start();
    • 优点:有返回值、可抛异常;缺点:实现复杂。

2. 线程生命周期状态+转换

线程6种状态:新建、就绪、运行、阻塞、等待、终止

  1. 新建:new Thread(),未启动;
  2. 就绪:start(),等待CPU调度;
  3. 运行:获得CPU,执行run();
  4. 阻塞:等待锁、IO,释放CPU;
  5. 等待:wait()/join(),需唤醒;
  6. 终止:run()执行完毕/异常退出。

3. synchronized作用?修饰内容+底层原理

作用

保证线程安全,实现原子性、可见性、有序性,防止多线程并发冲突。

修饰内容
  1. 修饰实例方法:锁当前对象
  2. 修饰静态方法:锁类对象
  3. 修饰代码块:锁指定对象
底层原理
  • 方法:ACC_SYNCHRONIZED标识;
  • 代码块:monitorenter/monitorexit指令,依赖JVM的Monitor锁。

4. volatile关键字作用?能保证原子性吗

作用
  1. 保证可见性:线程修改值立即同步到主内存,其他线程可见;
  2. 禁止指令重排:保证代码执行顺序。
不能保证原子性
  • 原因:volatile仅保证单次读/写原子性,复合操作(i++)不原子
  • 场景:适合状态标记量(如停止标志),不适合计数。

5. 线程池核心参数?创建方式

核心参数
  1. corePoolSize:核心线程数,常驻线程;
  2. maximumPoolSize:最大线程数;
  3. keepAliveTime:非核心线程空闲时间;
  4. unit:时间单位;
  5. workQueue:阻塞队列;
  6. threadFactory:线程工厂;
  7. handler:拒绝策略。
创建方式
  1. Executors工具类(不推荐,易OOM);
  2. new ThreadPoolExecutor()(推荐,自定义参数)。

6. Callable和Runnable的区别?FutureTask作用

Callable vs Runnable
特性 Runnable Callable
方法 run() call()
返回值
异常 不抛异常 可抛受检异常
FutureTask作用
  • 包装Callable任务,实现Runnable+Future接口;
  • 接收call()返回值,通过get()获取结果,支持异步获取。

六、框架与数据库

1. Spring核心思想?IOC和AOP

  • 核心思想:IOC(控制反转)、AOP(面向切面编程)
  1. IOC:将对象创建、依赖注入交给Spring容器管理,无需手动new,降低耦合;
  2. AOP:横向抽取通用逻辑(日志、事务),不修改业务代码,实现功能增强。

2. Spring IOC原理?Bean生命周期

IOC原理
  1. 扫描配置类/XML,解析Bean定义;
  2. 实例化Bean(反射创建对象);
  3. 依赖注入(填充属性);
  4. 初始化Bean(执行初始化方法);
  5. 容器关闭,销毁Bean。
Bean生命周期

实例化→属性填充→初始化→使用→销毁。

3. MyBatis核心组件?#{}和${}区别

核心组件
  1. SqlSessionFactory:会话工厂;
  2. SqlSession:数据库会话;
  3. Mapper接口:数据操作接口;
  4. 映射文件:SQL语句配置。
#{} / ${}
  • #{} :预编译,防止SQL注入,参数用?占位;
  • ${} :字符串拼接,有SQL注入风险,适用于动态表名/列名。

4. SQL基本操作?索引作用

基本操作
  • 增:INSERT INTO 表 VALUES(值);
  • 删:DELETE FROM 表 WHERE 条件;
  • 改:UPDATE 表 SET 字段=值 WHERE 条件;
  • 查:SELECT 字段 FROM 表 WHERE 条件。
索引作用
  • 加快查询速度,减少全表扫描;
  • 缺点:增删改效率降低,占用磁盘空间。

5. InnoDB和MyISAM区别?主键外键作用

InnoDB vs MyISAM
特性 InnoDB MyISAM
事务支持 支持 不支持
锁机制 行锁 表锁
外键 支持 不支持
崩溃恢复 支持 不支持
主键/外键作用
  • 主键:唯一标识表中记录,非空、唯一
  • 外键:关联两张表,保证数据一致性,防止脏数据。

七、综合

1. Java8新特性?Lambda、Stream作用

新特性
  1. Lambda表达式;
  2. Stream API;
  3. 函数式接口;
  4. 默认方法/静态方法;
  5. Optional;
  6. 新日期API。
Lambda/Stream作用
  • Lambda:简化匿名内部类,简化代码,支持函数式编程;
  • Stream:对集合数据高效操作(过滤、排序、映射),支持并行流。

2. 什么是微服务?Spring Boot和Spring Cloud区别

  • 微服务:将单体应用拆分为多个独立、可部署的小型服务,服务间通过API通信,高可用、易扩展。
Spring Boot vs Spring Cloud
  • Spring Boot:快速构建单体应用,简化配置,内嵌容器;
  • Spring Cloud:微服务生态,基于Spring Boot,提供服务注册、配置、熔断等微服务组件。
相关推荐
小谢小哥2 小时前
53-熔断降级详解
java·后端·架构
CodeMartain2 小时前
shardingsphere-spring 实现数据分片(一)
java·后端·spring
hhb_6182 小时前
C Shell脚本编程与系统管理技术实践指南
java·c语言·开发语言
小雅痞2 小时前
[Java][Leetcode hard] 68. 文本左右对齐
java·开发语言·leetcode
一直跑2 小时前
同一台服务器上(同局域网)的其他账号访问自己的数据(没有sudo权限和无 ACL和无共同组)
java·linux·服务器
梦想的颜色2 小时前
js document 节点增删改查、样式设计全解析
java·前端·javascript
老友@2 小时前
Jenkins 中 Node 版本异常排查:Alpine + musl 导致的兼容问题(lts-alpine-jdk17)
java·servlet·jenkins
笛卡尔的心跳2 小时前
Spring MVC 注解
java·spring·mvc
Kiyra2 小时前
为什么远程调用别包进 Spring 事务里
java·后端·spring