news 2026/2/25 23:49:43

java基础八股

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java基础八股

怎么理解面向对象?简单说说封装继承多态

面向对象是一种编程范式,它将现实世界中的事物抽象为对象,对象具有属性(称为字段或属性)和行为(称为方法)。面向对象编程的设计思想是以对象为中心,通过对象之间的交互来完成程序的功能,具有灵活性和可扩展性,通过封装和继承可以更好地应对需求变化。

Java面向对象的三大特性包括:封装、继承、多态。

https和http的区别?

一、根本区别:是否加密

特性HTTPHTTPS
全称HyperText Transfer ProtocolHyperText Transfer ProtocolSecure
安全性❌ 明文传输,数据可被窃听、篡改加密传输,防窃听、防篡改、防冒充
端口80443
URL 前缀http://https://

序列化和反序列化的原理

  • 序列化:把内存中的对象→ 转成可存储或传输的格式(如字节流、JSON、XML);
  • 反序列化:把字节流/文本→ 重新变回内存中的对象

1.序列化过程

  • 程序遍历对象的字段(属性)
  • 按照某种格式规则(如 Java 的ObjectOutputStream、JSON、Protobuf);
  • 将对象的类型信息 + 数据值转为字节流或字符串
  • 可保存到文件、数据库,或通过网络发送。

2.反序列化过程

  • 读取字节流/字符串;
  • 根据其中的类型信息,创建对应类的新实例;
  • 把数据填充回对象的字段
  • 最终得到一个结构和数据都相同的对象(但内存地址不同)。

BIO、NIO、AIO区别是什么?

模型全称核心特点
BIOBlocking I/O(同步阻塞 I/O)一个连接一个线程,读写会阻塞当前线程
NIONon-blocking I/O(同步非阻塞 I/O)一个线程管理多个连接,靠轮询(Selector)检查是否就绪
AIOAsynchronous I/O(异步非阻塞 I/O)操作完成后系统主动通知你,全程不阻塞
特性BIONIOAIO
模型同步阻塞同步非阻塞异步非阻塞
线程模型1 连接 : 1 线程1 线程 : 多连接(Reactor 模式)1 线程 : 多连接(Proactor 模式)
是否阻塞否(但需轮询)否(系统通知)
编程难度简单较复杂复杂
吞吐量低(连接多时崩溃)极高(理想场景)
典型应用Tomcat 早期版本Netty、Redis、Kafka、Tomcat NIOJava AIO(较少用)
操作系统支持通用Linux: epoll, Windows: IOCPWindows: IOCP, Linux: 依赖 libaio(不完善)

1.BIO(Blocking I/O)—— 老派服务员

  • 工作方式
    • 服务端每 accept 一个客户端连接,就创建一个新线程处理;
    • 调用read()/write()时,线程会一直阻塞,直到数据读完或写完。
  • 缺点
    • 连接数多 → 线程爆炸(内存耗尽、上下文切换开销大);
    • 大量线程空等(如客户端发数据慢),资源浪费。
  • 适用场景:连接数少、数据交互频繁且稳定的场景(如内部系统)。

🍽️类比
餐厅有 100 个客人,老板请了 100 个服务员,每人盯一个客人——即使客人在发呆,服务员也不能干别的。

2.NIO(Non-blocking I/O)—— 多路复用经理

  • 核心组件Buffer(缓冲区)、Channel(通道)、Selector(选择器)
  • 工作方式
    • 一个线程通过Selector 轮询多个 Channel
    • Channel 设置为非阻塞模式read()若无数据立即返回 0,不卡线程;
    • 只有当 Selector 告诉你“某个 Channel 有数据可读”时,才去处理。
  • 优点
    • 单线程可处理成千上万连接(如 Netty、Redis);
    • 避免线程阻塞,资源利用率高。
  • 缺点
    • 编程复杂(需手动管理 Buffer、状态机);
    • 轮询仍有 CPU 开销(但远小于 BIO 的线程开销)。

🍽️类比
1 个经理拿着对讲机(Selector),监听所有餐桌(Channel)。只有客人按铃(数据就绪),经理才过去服务。

3.AIO(Asynchronous I/O)—— 主动通知的智能系统

  • 工作方式(Java 7+,基于java.nio.channels.AsynchronousChannel):
    • 发起read()操作时,立即返回,不阻塞线程;
    • 系统在后台完成 I/O,完成后主动通知(回调或 Future);
    • 线程可以去做其他事,完全不用关心 I/O 是否就绪。
  • 优点
    • 真正的异步,无需轮询;
    • 在高并发、低活跃连接场景下效率极高(如聊天服务器)。
  • 缺点
    • 依赖操作系统支持(Linux 下基于 epoll 的模拟,Windows 下原生支持好);
    • Java 生态中使用较少(Netty 等主流框架仍用 NIO);
    • 调试和编程模型较复杂(回调地狱)。

🍽️类比
客人点完餐,系统自动记录。厨房做好后,主动呼叫服务员送餐——服务员全程不用盯着。

集合

java基础04(集合、异常、引用、线程)---java八股_java八股 异常-CSDN博客

Java中的线程安全的集合是什么?

早期线程安全集合

1.Vector

  • 线程安全的List
  • 所有方法加synchronized全局锁);
  • 性能差,已被CopyOnWriteArrayListCollections.synchronizedList()替代。

2.Hashtable

  • 线程安全的Map
  • 不允许null,所有方法加synchronized
  • 已被ConcurrentHashMap完全取代

3.Stack

  • 继承自Vector,同样线程安全但性能差;
  • 推荐用Deque代替(如ArrayDeque)。

java.util.concurrent包下的高性能并发集合

1.ConcurrentHashMap

  • 线程安全的Map
  • JDK 1.8+ 使用CAS + synchronized(锁桶头),支持高并发读写;

2.CopyOnWriteArrayList

  • 线程安全的List
  • 写时复制(Copy-On-Write):每次修改(add/remove)都复制整个底层数组,读操作直接访问原数组(无锁);
  • 适合“读多写少”场景(如监听器列表、白名单);
  • 写操作开销大,不适合频繁修改。

3.CopyOnWriteArraySet

  • 基于CopyOnWriteArrayList实现的线程安全Set
  • 同样适用于读多写少场景。

4.BlockingQueue(阻塞队列)—— 生产者-消费者模型核心

特点
ArrayBlockingQueue有界队列,基于数组,FIFO
LinkedBlockingQueue可选有界(默认无界),基于链表,高吞吐
SynchronousQueue不存储元素,每个 put 必须等待 take
PriorityBlockingQueue支持优先级的无界队列

✅ 所有操作线程安全,天然支持线程间协作

ArrasyLIst线程不安全,多线程下会报什么异常?

1、最常见的异常:ConcurrentModificationException(并发修改异常)

什么时候抛出?

  • 当一个线程正在遍历(迭代)ArrayList(比如用for-eachiterator()),
  • 另一个线程同时修改了列表结构(如添加、删除元素),

2.数组越界(ArrayIndexOutOfBoundsException)

  • 在扩容过程中(ensureCapacityInternal),多个线程同时修改size和底层数组elementData
  • 可能导致某个线程写入的索引超出当前数组长度。

LinkdeList多线程下会报什么异常?

1.ConcurrentModificationException(并发修改异常)

  • 触发场景:一个线程在遍历LinkedList(如 for-each、iterator()),另一个线程同时修改结构add/remove)。
  • 原因LinkedList也实现了fail-fast 机制,内部有modCount计数器,迭代时发现修改就抛异常。

2.NullPointerException(空指针异常)

  • 这是LinkedList特有的高风险问题!
  • 原因LinkedList的节点(Node)通过prevnext指针连接。
    多线程并发修改(如两个线程同时add)可能导致:
    • 链表结构被破坏(指针错乱);
    • 某个节点的nextprev被设为null,但逻辑上不应为空;
    • 后续操作(如遍历、get())访问null.next→ 抛NPE

CopyonWriteArraylist是如何实现线程安全的

CopyOnWriteArrayList底层也是通过一个数组保存数据,使用volatile关键字修饰数组,保证当前线程对数组对象重新赋值后,其他线程可以及时感知到。

public class CopyOnWriteArrayList<E> { private transient volatile Object[] array; // 底层数组,volatile 保证可见性 final transient ReentrantLock lock = new ReentrantLock(); }
  • arrayvolatile的:确保一个线程修改后,其他线程能立即看到新数组;
  • 所有写操作先加锁,再复制数组,最后原子地替换array引用。

集合遍历的方法有哪些?

  • 普通 for 循环:可以使用带有索引的普通 for 循环来遍历 List。
  • 增强 for 循环(for-each循环):用于循环访问数组或集合中的元素。
  • Iterator 迭代器:可以使用迭代器来遍历集合,特别适用于需要删除元素的情况。
    Iterator<String> iterator = list.iterator(); while(iterator.hasNext()) { String element = iterator.next(); System.out.println(element); }
  • 使用 forEach 方法:Java 8引入了 forEach 方法,可以对集合进行快速遍历。
    list.forEach(element ->System.out.println(element));
  • 使用 forEach 方法:Java 8引入了 forEach 方法,可以对集合进行快速遍历。
    list.stream().forEach(element ->System.out.println(element));

Hashtable的底层原理

底层数据结构:数组 + 链表

  • Hashtable内部使用一个Entry[] table数组(JDK 8 之前);
  • 每个Entry是一个链表节点,包含:
    • hash:键的哈希值
    • key
    • value
    • next:指向下一个节点(解决哈希冲突)
private transient Entry<?,?>[] table; // 哈希桶数组 private transient int count; // 当前元素个数 private int threshold; // 扩容阈值 = capacity * loadFactor private final float loadFactor; // 负载因子,默认 0.75f

线程安全:全表 synchronized

⚠️ 缺点:

  • 并发性能极差(高并发下成为瓶颈);
  • 即使多个线程操作不同 key,也会互相阻塞。
  • 所有 public 方法都用synchronized修饰
  • 锁的是整个Hashtable对象(this);
  • 同一时间只允许一个线程操作,其他线程阻塞。

HashMap和hashtable的区别

特性HashMapHashtable
线程安全❌ 不安全✅ 安全(所有方法加synchronized
null 键/值✅ 允许一个nullkey,多个nullvalue完全不允许(会抛NullPointerException
初始容量1611
扩容方式容量 × 2容量 × 2 + 1
底层结构(JDK 8+)数组 + 链表 +红黑树(链表长度 ≥8 时转树)仅数组 + 链表(无红黑树优化)
继承关系extends AbstractMapextends Dictionary(已过时的抽象类)
迭代器fail-fastfail-fast
推荐使用✅ 单线程首选已过时,不推荐

ConcurrentHashMap

java线程-并发编程-CSDN博客

讲讲currenthashmap原理,分别讲了1.7和1.8的原理

特性JDK 1.7JDK 1.8
核心结构Segment 数组 + HashEntry 链表Node 数组 + 链表/红黑树
并发策略分段锁(ReentrantLock)CAS + synchronized(锁单个 bin)
锁粒度Segment 级(较粗)桶(bin)级(更细)
是否支持红黑树❌ 否✅ 是
扩容机制单线程 per Segment多线程协作扩容
内存占用高(预分配 Segment)低(按需分配)
读操作无锁无锁(volatile 保证)
性能更好(尤其高并发写)

JDK 1.7 版本:分段锁(Segment)

核心思想:“分而治之” —— 把整个哈希表分成多个段(Segment),每段独立加锁

1. 底层结构

  • ConcurrentHashMap内部包含一个Segment[] segments数组
  • 每个Segment继承自ReentrantLock相当于一个小的 HashMap
  • 每个Segment内部是一个HashEntry[]数组 + 链表。'

2. 并发机制:分段锁(Segment Locking)

  • 默认有16 个 SegmentconcurrencyLevel = 16);
  • 当线程操作 key 时:
    1. 先通过hash(key)计算出属于哪个 Segment;
    2. 只对该 Segment 加锁(其他 Segment 可并发访问);
    3. 在该 Segment 内部执行 put/get/remove。

3. 扩容

  • 每个 Segment 独立扩容(不是整个 Map 扩容);
  • 扩容时锁住当前 Segment,不影响其他 Segment。

JDK 1.8 版本:CAS + synchronized(取消 Segment)

核心思想:“更细粒度的锁” —— 直接对每个桶(bin)加锁,结合 CAS 优化

1. 底层结构(与 HashMap 几乎一致)

  • 直接使用Node[] table(类似 HashMap 的 Node);
  • 支持链表 + 红黑树(链表长度 ≥8 且容量 ≥64 时转树);
  • 取消了 Segment,结构更简洁。

2. 并发机制:CAS + synchronized

当执行put(key, value)时:

  1. 计算hash(key),定位到table[i]
  2. 如果table[i] == null
    • 使用CAS尝试直接插入新节点(无锁);
  3. 如果table[i] != null(存在链表或树):
    • table[i]的头节点加synchronized
    • 在同步块内遍历链表/树,执行插入或更新。

优点

  • 锁粒度更细:只锁单个桶(bin),不是整个 Segment;
  • 减少内存开销(无需预分配 Segment);
  • 利用 CAS 避免锁竞争(空桶直接 CAS 插入);
  • 支持红黑树,提升长链表性能。

3. 读操作(get)完全无锁

  • 利用volatile 语义保证可见性:
    • Node.valNode.next都是volatile
    • 写操作通过Unsafe.putObjectVolatile()保证立即可见;
  • 所以get()不需要加锁,性能极高。

4. 扩容(transfer)

  • 支持多线程协助扩容
  • 当一个线程发现需要扩容时:
    • 创建新数组;
    • 自己负责迁移一部分数据;
    • 其他写线程在操作时发现正在扩容,会主动帮忙迁移(提高效率);
  • 迁移过程中,旧数组的桶会被标记为ForwardingNode(转发节点),get()请求会自动去新数组查。

分段锁怎么加锁的?

在 ConcurrentHashMap 中,将整个数据结构分为多个 Segment,每个 Segment 都类似于一个小的 HashMap,每个 Segment 都有自己的锁,不同 Segment 之间的操作互不影响,从而提高并发性能。

每个 Segment 都有自己的锁,不同 Segment 之间的操作互不影响,从而提高并发性能。然后再在该 Segment 上加锁,而不是像传统的 HashMap 一样对整个数据结构加锁。这样可以使得不同 Segment 之间的操作并行进行,提高了并发性能.

ConcurrentHashMap用了悲观锁还是乐观锁?

悲观锁和乐观锁都有用到。

添加元素时首先会判断容器是否为空:

  • 如果为空则使用 volatile 加CAS (乐观锁)来初始化。

  • 如果容器不为空,则根据存储的元素计算该位置是否为空。

  • 如果根据存储的元素计算结果为空,则利用CAS(乐观锁)设置该节点;

  • 如果根据存储的元素计算结果不为空,则使用synchronized(悲观锁),然后,遍历桶中的数据,并替换或新增节点到桶中,最后再判断是否需要转为红黑树,这样就能保证并发访问时的线程安全了。

list转map的方法

最推荐、最简洁的方式是使用 Java 8 的 Stream API +Collectors.toMap()

方法一:Java 8+ Stream

Map<K, V> map = list.stream() .collect(Collectors.toMap( element -> keyExtractor, // 如: User::getId element -> valueMapper // 如: User::getName )); // 保留新值 Map<Integer, String> map = users.stream() .collect(Collectors.toMap( User::getId, User::getName, (oldValue, newValue) -> newValue // 冲突时用 newValue ));

方法二:手动 for 循环(兼容老版本 Java)

Map<Integer, String> map = new HashMap<>(); for (User user : users) { map.put(user.getId(), user.getName()); }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/23 7:28:12

Shutter Encoder专业视频编码工具完全指南

Shutter Encoder专业视频编码工具完全指南 【免费下载链接】shutter-encoder A professional video compression tool accessible to all, mostly based on FFmpeg. 项目地址: https://gitcode.com/gh_mirrors/sh/shutter-encoder Shutter Encoder是一款基于Java开发的专…

作者头像 李华
网站建设 2026/2/25 8:53:37

抖音无水印视频下载完整教程:快速保存高清原片

想要完美收藏抖音上的精彩视频内容&#xff0c;却总是被烦人的水印困扰&#xff1f;douyin_downloader抖音无水印下载器正是你需要的终极解决方案。这款开源工具支持抖音视频无水印下载和批量保存&#xff0c;让你轻松获取原始画质的高清视频文件。 【免费下载链接】douyin_dow…

作者头像 李华
网站建设 2026/2/25 2:33:41

AppleRa1n终极指南:iOS激活锁绕过完整解决方案

AppleRa1n终极指南&#xff1a;iOS激活锁绕过完整解决方案 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 当你面对一台被激活锁困住的iPhone时&#xff0c;是否感到束手无策&#xff1f;iOS激活锁绕过…

作者头像 李华
网站建设 2026/2/2 10:27:32

ZerotierFix:解锁Android设备网络连接新境界

ZerotierFix&#xff1a;解锁Android设备网络连接新境界 【免费下载链接】ZerotierFix An unofficial Zerotier Android client patched from official client 项目地址: https://gitcode.com/gh_mirrors/ze/ZerotierFix 还在为移动设备网络连接限制而烦恼吗&#xff1f…

作者头像 李华
网站建设 2026/2/24 4:08:46

【python大数据毕设实战】双十一淘宝美妆数据可视化与分析系统、Hadoop、计算机毕业设计、包括数据爬取、数据分析、数据可视化、机器学习、实战教学

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

作者头像 李华
网站建设 2026/2/21 0:25:37

英雄联盟智能助手:League Akari完整使用教程

英雄联盟智能助手&#xff1a;League Akari完整使用教程 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 还在为繁琐的游戏操作烦恼…

作者头像 李华