加载中

面经

文章分类

浏览该分类下的所有文章

48 篇文章 4

Java基础(一)

Java 通过将源代码编译成平台无关的字节码,由各平台的 JVM 翻译为机器码实现“一次编写、处处运行”。一个 .java 文件可包含多个类,但只能有一个 public 类且必须与文件名同名。访问权限分为 private、default、protected、public 四级,类仅有 default 与 public。数据类型分为 8 种基本类型(整数、浮点、字符、布尔)和引用类型(数组、类、接口),基本类型有固定内存占用和默认值;成员变量(实例/类变量)有默认初始化,局部变量无默认值且存栈中。包装类为基本类型提供对象特性,支持自动装箱/拆箱,简化基本类型与对象之间的转换。比较 Integer 与 Double 时应先转换为相同的基本数值(如 double),再使用 == 或相应方法判断相等。

Java基础(二)

本文阐述了Java基础知识,包括int与包装类Integer的区别及==比较规则;面向对象的概念、封装、继承、多态三大特征及抽象意义;封装的目的与实现方式;多态的实现原理、单继承原因及多继承的限制;重写与重载的区别、构造方法不可重写;以及Object类常用方法(getClass、equals、hashCode、toString、wait/notify、clone、finalize)的作用。

Java基础(三)

hashCode 与 equals 必须保持一致:相等对象的 hashCode 必须相同,hash 相同不一定相等,因此业务类常同时重写两者。== 比较引用地址,equals 可重写比较内容。String 为 final 不可变,存于常量池,使用字面量比 new 更省内存。String、StringBuffer、StringBuilder 的区别在于是否可变及是否线程安全,拼接时应根据是否含变量、是否需线程安全选择 +、concat、StringBuilder 或 StringBuffer。接口只定义规范(无构造器),可多实现;抽象类可提供部分实现并有构造器,但只能单继承。面向接口编程有助于降低耦合、提升可扩展性。

Java基础(四)

文章系统阐述了Java异常处理流程(try‑catch‑finally、异常层次、抛出与传播),static 与 final 的作用与区别,泛型的意义、擦除机制以及通配符上下界;进一步介绍了反射的原理与常见应用(JDBC、框架、AOP),并简要说明了强、软、弱、虚四种引用及其垃圾回收行为。

集合类(一)

介绍Java集合体系:Collection分为Set、List、Queue,Map为键值映射;列举常用实现类及其线程安全情况,说明使用Collections或java.util.concurrent提供的并发集合。重点阐述Map实现,尤其HashMap的结构、put过程、扩容与冲突处理(链表转红黑树)以及线程不安全原因;比较HashMap、Hashtable、ConcurrentHashMap、LinkedHashMap的特性与实现原理。

集合类(二)

本文系统介绍了Java集合类的核心实现与区别。TreeMap 基于红黑树实现键的排序;Map、Set、List 在有序性和唯一性上的差异;ArrayList 与 LinkedList 分别基于数组和双向链表,前者随机访问 O(1) 而后者插删更快;线程安全的 List 包括 Vector、Collections.synchronizedList 与 CopyOnWriteArrayList,后者通过写时复制实现读写分离。HashSet 依赖 HashMap,TreeSet 使用红黑树并支持自然或定制排序。BlockingQueue 提供四组插入、移除、检查方法,以满足不同阻塞或非阻塞需求;以 ArrayBlockingQueue 为例,采用 ReentrantLock 与 Condition 实现阻塞机制。最后概述了 Stream 的中间操作(filter、map、sorted 等)和终端操作(forEach、reduce、collect 等),以及其在集合聚合中的作用。

IO

文章系统介绍了Java IO流的分类与常用类,指出大文件应采用缓冲流或NIO的内存映射方式读取。随后阐述NIO的核心Channel、Buffer、Selector及其属性和跨平台实现。接着讲解对象序列化/反序列化机制、serialVersionUID的作用,并列举JSON、Protobuf、Thrift、Avro等主流序列化工具及其特点,最后提供不使用JSON时的实现思路。

多线程(一)

本文系统阐述了Java多线程的基本概念与实现技术。首先介绍了三种创建线程的方式——继承Thread类、实现Runnable接口和实现Callable接口,并比较了各自的优缺点,推荐使用Runnable/Callable。随后列举了Thread类的常用构造、静态及实例方法。重点说明了run()与start()的区别以及线程只能被启动一次的限制。接着描述了线程的五阶段生命周期(新建、就绪、运行、阻塞、死亡)及其状态转换。随后讨论了实现同步的手段,包括synchronized方法/代码块、ReentrantLock、volatile、原子变量。进一步介绍了线程间通信方式:Object 的 wait/notify/notifyAll、Lock 的 Condition(await/ signal/ signalAll)以及 BlockingQueue。最后对 wait 与 sleep、notify 与 notifyAll 的差异进行了对比说明。

多线程(二)

子线程先执行可在启动后立即调用join,使主线程阻塞直至子线程结束。线程阻塞情况包括sleep、阻塞IO、获取同步监视器、等待notify及suspend。synchronized 为JVM关键字,底层通过monitorenter/monitorexit 与对象头Mark Word 实现,支持代码块、方法及静态方法(类锁),但不能修饰静态代码块。Lock 为接口,需显式释放,可设超时、检测成功、支持公平/非公平、读写锁。ReentrantLock 基于AQS 的独占模式实现,内部有公平与非公平子类。除synchronized/Lock外,可用volatile、原子类、ThreadLocal、不可变对象保证安全。悲观锁使用synchronized/Lock,乐观锁依赖CAS。公平锁按等待队列顺序获取,非公平锁抢占更快。JDK 1.6 以后同步锁经历无锁→偏向锁→轻量级锁→重量级锁的升级,均通过Mark Word 与CAS 控制。

多线程(三)

JUC是java.util.concurrent包,提供原子类、锁/Condition、线程池、阻塞队列、并发容器和同步器等基础组件。AQS是构建锁等同步器的骨架,负责同步状态、等待队列和线程阻塞/唤醒,常见实现有ReentrantLock、Semaphore、ReentrantReadWriteLock等。LongAdder通过分段计数降低CAS竞争,适合高并发计数场景。ThreadLocal为每个线程提供独立的变量存储,内部使用ThreadLocalMap并采用线性探查处理哈希冲突。线程池通过复用线程提升性能,核心类包括Executor、ThreadPoolExecutor、Future等,工作流程为创建核心线程、入队任务、饱和时执行拒绝策略。线程池状态有RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED,拒绝策略包括Abort、Discard、DiscardOldest、CallerRuns;队列大小一般依据CPU密集或IO密集程度进行调节。

JVM(一)

JVM由类加载器、运行时数据区、执行引擎和本地接口四部分构成。运行时数据区包括程序计数器、虚拟机栈、本地方法栈、堆、方法区等,分别负责指令位置、方法调用、Native 方法、对象存储和类信息。JVM启动先定位JRE、装载并初始化后,通过类加载器加载class文件,执行引擎解释或JIT编译字节码。Java 程序经编译成字节码、加载、实例化、解释执行。文中还说明本地方法栈、程序计数器的作用及内存分布、类和局部变量的存放位置、编译与类加载的主要阶段。

JVM(二)

JVM 在 Eden 区满时触发 Minor GC,老年代空间不足或达到阈值时产生 Full GC,可通过扩容、调节代大小、禁用 System.gc 等方式降低 Full GC。对象是否可回收由 GC Roots 的可达性决定,引用计数因循环引用而不被采用。对象在 Survivor 区存活若干次后(默认 15 次)晋升老年代,老年代不使用标记‑复制是因复制成本高。新生代划分为 Eden 与两个 Survivor(比例约 8:1),利用复制避免碎片。常见 GC 算法包括标记‑清除、标记‑复制、标记‑整理;不同代采用不同算法以平衡效率和空间。G1 将堆划分为 Region,按停顿时间优先回收价值最高的 Region;CMS 采用并发标记‑清除,停顿短但易产生碎片和并发失败。内存泄漏指对象仍被引用而无法回收,溢出指申请内存超出上限,解决方案包括及时释放引用、避免大对象长驻、合理调参等。