跳转到内容

JavaSE笔记

💡

JavaSE(Java Standard Edition)是Java体系的基础,涵盖了Java语言核心语法、面向对象编程、集合框架、IO流、多线程、反射、JDK8新特性等内容。


一、基础语法

1.1 数据类型

类型

关键字

字节

范围/说明

字节型

byte

1

-128 ~ 127

短整型

short

2

-2^15 ~ 2^15-1

整型

int

4

-2^31 ~ 2^31-1(默认)

长整型

long

8

-2^63 ~ 2^63-1(L后缀)

浮点型

float

4

单精度(F后缀)

双精度

double

8

双精度(默认)

字符型

char

2

Unicode 0 ~ 65535

布尔型

boolean

1(虚拟)

true / false

关键点:自动类型提升 byte→short→int→long→float→double;char→int。小数默认double,float必须加F;long建议加大写L。

1.2 包装类与自动拆装箱

基本类型

包装类

byte / short / int / long

Byte / Short / Integer / Long

float / double

Float / Double

char

Character

boolean

Boolean

💡

重点:Integer缓存池默认 -128 ~ 127,超出范围 == 比较为false(需用equals)。valueOf()从缓存取,new Integer()每次新建对象(已废弃JDK9+)。

1.3 String

📌

不可变性:String被final修饰,底层用final byte[]存储(JDK9+从char[]改为byte[]节省空间)。任何修改操作都返回新String对象。

  • String常量池:双引号直接赋值从常量池取;new String()在堆创建新对象,intern()手动入池
  • StringBuilder(线程不安全,性能高)vs StringBuffer(线程安全,synchronized方法)
  • 拼接原理:+ 操作符编译后为StringBuilder.append;循环内拼接务必显式用StringBuilder

1.4 == vs equals()

  • ==:比较栈中值。基本类型比值,引用类型比地址
  • equals():Object默认用==比较地址;String重写后比较内容;自定义类需重写equals()(同时重写hashCode())
  • hashCode():两个对象equals相等→hashCode必相等;hashCode相等≠equals相等(哈希冲突)

1.5 流程控制

  • switch:支持byte/short/int/char/String/enum;case穿透需break;JDK14+支持箭头表达式和多case合并
  • 增强for循环:for(Type x : iterable) 底层调用Iterator,遍历时不能修改集合(ConcurrentModificationException)
  • break vs continue:break跳出整个循环/switch;continue跳过本次迭代;带标签可跳出外层循环

二、面向对象

2.1 封装、继承、多态

特性

核心

实现方式

封装

隐藏内部细节,暴露接口

private属性 + public getter/setter

继承

复用代码,is-a关系

extends(单继承),子类拥有父类非private成员

多态

同一接口不同实现,提高扩展性

父类引用指向子类对象;方法重写(运行时多态)+ 方法重载(编译时多态)

2.2 访问修饰符

修饰符

本类

同包

子类

其他

private

default

protected

public

2.3 抽象类 vs 接口

对比

抽象类(abstract class)

接口(interface)

构造器

成员变量

任意

默认 public static final

方法

抽象方法 + 普通方法

抽象方法(JDK8+ default/static, JDK9+ private)

继承/实现

单继承(extends)

多实现(implements),接口可多继承接口

语义

is-a,模板设计

can-do,行为规范

2.4 内部类

  • 成员内部类:可以访问外部类所有成员;创建需外部类实例:outer.new Inner()
  • 静态内部类:static修饰,只能访问外部类static成员;直接new Outer.Inner()
  • 局部内部类:定义在方法中,作用域仅该方法内
  • 匿名内部类:new Interface() { 实现方法 },常用于回调。JDK8+可用Lambda替代

三、异常处理

3.1 异常体系

📌

Throwable → Error(不可处理,如OOM/StackOverflow) + Exception。Exception → RuntimeException(非受检,编译不强制) + 受检异常(必须try-catch或throws)。

常见RuntimeException

常见受检异常

常见Error

NullPointerException

IOException

OutOfMemoryError

IndexOutOfBoundsException

SQLException

StackOverflowError

ClassCastException

ClassNotFoundException

NoClassDefFoundError

ArithmeticException

FileNotFoundException

IllegalArgumentException

InterruptedException

3.2 try-catch-finally

  • finally:一定执行(System.exit(0)除外)。若finally中有return,会覆盖catch中的return
  • try-with-resources(JDK7+):try(资源定义) 自动调用close(),资源必须实现AutoCloseable接口
  • 异常链:throw new RuntimeException("msg", originalException) 保留根因

四、集合框架

4.1 整体体系

💡

Collection(单列集合) → List(有序可重复)、Set(无序不可重复)、Queue(队列)。Map(双列集合,键值对)。

4.2 List

ArrayList

LinkedList

Vector

底层

Object[] 动态数组

双向链表

Object[] + synchronized

查询

O(1)

O(n)

O(1)(线程安全)

增删

O(n)(尾部O(1)摊销)

O(1)(定位到位置后)

O(n)

扩容

1.5倍(无参初始化空数组,首次add扩容到10)

无,链表

2倍

线程安全

是(已淘汰,用CopyOnWriteArrayList)

4.3 Set

  • HashSet:基于HashMap(key存元素,value为PRESENT常量)。无序,O(1)增删查
  • LinkedHashSet:继承HashSet,底层LinkedHashMap。保持插入顺序,O(1)
  • TreeSet:基于TreeMap(红黑树)。元素自然排序或Comparator排序,O(log n)

4.4 Map

HashMap

LinkedHashMap

TreeMap

底层

数组+链表+红黑树(JDK8+)

HashMap+双向链表

红黑树

顺序

无序

插入顺序/访问顺序

键自然排序/Comparator

null键

允许1个

允许1个

不允许

复杂度

O(1) ~ O(n)/O(log n)

O(1)

O(log n)

线程安全

否 → ConcurrentHashMap

HashMap关键机制(JDK8+):

  • put流程:计算hash→(n-1)&hash确定桶位→桶空直接插入→桶非空,链表尾插(JDK7头插)→链表长度≥8 && 数组长度≥64转为红黑树→扩容(len≥threshold=capacity*loadFactor)时2倍扩容,rehash
  • 初始容量16,负载因子0.75,容量必为2的幂(便于取模优化)。链表≤6时树退化为链表
  • JDK7头插法 → 并发扩容可能死循环(环形链表);JDK8尾插法修复

4.5 ConcurrentHashMap

  • JDK7:分段锁(Segment extends ReentrantLock),默认16段,并发度16
  • JDK8:CAS + synchronized锁链表/红黑树头节点(锁粒度更细),并发度更高
  • put:桶为空→CAS自旋写入;桶非空→synchronized锁头节点插入/更新;扩容时协助transfer
  • get:无锁(volatile保证可见性),全程CAS-free

五、泛型

5.1 核心概念

  • 类型擦除:Java泛型是编译时检查,编译后擦除为边界类型(无边界→Object,有边界→上界类型),运行时无泛型信息
  • PECS原则:Producer Extends(读用? extends T),Consumer Super(写用? super T)
  • 泛型类/接口/方法:class Box<T> / <T> T method(T t)
💡

常见误区:泛型不支持基本类型(只能用包装类);不能new T()或new T[];instanceof无法检查泛型类型;static方法不能使用类的泛型参数(需定义为泛型方法)。


六、IO流

6.1 分类体系

  • 字节流:InputStream / OutputStream(FileInputStream, BufferedInputStream, ObjectInputStream)
  • 字符流:Reader / Writer(FileReader, BufferedReader, InputStreamReader)
  • 转换流:InputStreamReader(字节→字符)/ OutputStreamWriter(字符→字节),可指定编码

常用流

作用

注意

BufferedInputStream/Reader

带缓冲读写,减少IO次数

默认缓冲区8KB

ObjectInputStream/ObjectOutputStream

对象序列化/反序列化

类必须实现Serializable

DataInputStream/DataOutputStream

读写基本数据类型

与机器无关的数据格式

ByteArrayInputStream

内存中操作字节数组

不需要关闭

6.2 序列化

  • Serializable:标记接口。static和transient修饰的字段不序列化
  • serialVersionUID:版本控制,反序列化时校验;不显式定义会自动生成(字段变更会导致不一致)
  • 序列化深拷贝:通过ByteArrayOutputStream序列化再反序列化实现对象深拷贝

七、多线程

7.1 线程创建方式

方式

实现

特点

继承Thread

extends Thread,重写run()

单继承限制,不推荐

实现Runnable

implements Runnable,传入Thread

无返回值,推荐

实现Callable

implements Callable<V>,通过FutureTask获取结果

有返回值,可抛异常

线程池

ExecutorService.submit()

复用线程,推荐生产使用

7.2 线程生命周期(6种状态)

  • NEW → RUNNABLE(start) → BLOCKED(等待synchronized锁) / WAITING(wait/join无超时) / TIMED_WAITING(sleep/有超时wait) → TERMINATED

7.3 synchronized

  • 锁升级(JDK6+):无锁 → 偏向锁(记录线程ID)→ 轻量级锁(CAS自旋)→ 重量级锁(OS Mutex,自旋失败膨胀)
  • 修饰范围:实例方法(锁this)、静态方法(锁Class对象)、代码块(锁指定对象)
  • 底层实现:monitorenter/monitorexit指令;重量级锁基于OS Mutex

7.4 JUC锁(java.util.concurrent.locks)

📌

ReentrantLock:基于AQS(AbstractQueuedSynchronizer),公平锁(lock()直接入队) / 非公平锁(先CAS抢一次再入队)。支持可中断锁(lockInterruptibly)、超时获取锁(tryLock)、多条件变量(Condition)。

7.5 AQS原理

  • 核心:volatile int state(锁状态)+ CLH队列(双向链表存储等待线程)+ CAS修改state
  • 独占模式:state=0表示未锁定,加锁CAS(0,1)成功则获取,失败则入队park挂起;释放state=0唤醒后继
  • 共享模式:state代表可用资源数(如Semaphore),CAS递减;释放递增并唤醒等待线程链
  • AQS的实现:ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock、CyclicBarrier

7.6 线程同步工具

工具

作用

CountDownLatch

计数器,一个线程等待其他N个线程完成(一次性)

CyclicBarrier

屏障,N个线程相互等待后同时执行(可循环使用)

Semaphore

信号量,控制同时访问资源的线程数(限流)

Exchanger

两个线程交换数据

Phaser

多阶段同步屏障(JDK7+,增强版CyclicBarrier)

CompletableFuture

异步编排,串行/并行/聚合/异常处理(JDK8+)

7.7 线程池(ThreadPoolExecutor)

💡

7个参数:corePoolSize → maximumPoolSize → keepAliveTime(空闲非核心线程存活时间) → unit → workQueue(阻塞队列) → threadFactory → handler(拒绝策略)

  1. 执行流程:任务来 → 核心线程数未满则创建核心线程 → 已满则入队 → 队列满则创建非核心线程(上限maximumPoolSize) → 还满则执行拒绝策略
  2. 4种拒绝策略:AbortPolicy(抛异常,默认)、CallerRunsPolicy(调用者线程执行)、DiscardPolicy(直接丢弃)、DiscardOldestPolicy(丢弃队首)
  3. 常见线程池:newFixedThreadPool(固定)、newCachedThreadPool(弹性)、newSingleThreadExecutor(单线程)、newScheduledThreadPool(定时) — 均不推荐直接使用(队列无界,可能OOM)。建议手动new ThreadPoolExecutor指定参数

7.8 ThreadLocal

  • 原理:每个Thread维护ThreadLocalMap(ThreadLocal为key的弱引用),set/get实际操作当前线程的Map
  • 内存泄漏:ThreadLocal弱引用可被GC,但value是强引用,线程长期存活不remove会泄漏(线程池场景尤其严重)

7.9 volatile

  • 可见性:写volatile变量后立即刷新主内存,读之前从主内存读取(缓存一致性协议MESI/内存屏障)
  • 禁止指令重排序:内存屏障(LoadLoad/StoreStore/LoadStore/StoreLoad),经典应用DCL单例
  • 不保证原子性:i++仍非原子(读→改→写),需用AtomicInteger或synchronized

八、反射

8.1 核心API

  • 获取Class对象:类名.class / 对象.getClass() / Class.forName("全限定类名")
  • 创建对象:clazz.newInstance()(JDK9废弃) → clazz.getDeclaredConstructor().newInstance()
  • 获取字段:getFields()(public) / getDeclaredFields()(全部) → field.setAccessible(true)突破私有 → field.get(obj)/set(obj, val)
  • 获取方法:getMethods() / getDeclaredMethods() → method.invoke(obj, args)
💡

注意:反射绕过编译检查,性能低于直接调用(JDK优化后差距缩小);setAccessible(true)在JDK17+受模块系统限制可能失败。


九、注解

9.1 元注解与自定义注解

元注解

作用

@Target

定义注解使用位置(TYPE/FIELD/METHOD/PARAMETER等)

@Retention

SOURCE(源码级,编译丢弃) / CLASS(字节码级,运行时丢弃) / RUNTIME(运行时保留,反射可读)

@Documented

被javadoc收录

@Inherited

子类继承父类注解

@Repeatable

可重复标注(JDK8+)

9.2 注解处理器

  • 编译时:AbstractProcessor + @AutoService → 生成代码(Lombok、MapStruct基于此)
  • 运行时:通过反射读取注解,Spring框架大量使用

十、JDK8 新特性

10.1 Lambda表达式

  • 语法:(参数) → { 方法体 },单参数可省括号,单语句可省return和大括号
  • 本质:函数式接口(FunctionalInterface,有且仅有一个抽象方法的接口)的匿名实现
  • 常用函数式接口:Function<T,R>(转换)、Predicate<T>(判断)、Consumer<T>(消费)、Supplier<T>(供给)、BiFunction/BinaryOperator(二元)

10.2 Stream API

📌

三步操作:创建Stream(集合.stream()/数组Arrays.stream()/Stream.of())→ 中间操作(filter/map/sorted/distinct/limit/skip/flatMap,惰性执行) → 终止操作(collect/forEach/count/reduce/findFirst,触发计算)

  • collect(Collectors.toList()):收集为List/Set/Map;Collectors.groupingBy(分组)、partitioningBy(分区true/false)
  • reduce:归约操作,如求和/求积/拼接
  • 并行流:parallelStream(),底层ForkJoinPool,注意线程安全问题

10.3 Optional

  • 目的:优雅解决NPE,强制调用者处理null情况
  • 创建:Optional.of(T)(非空)、Optional.ofNullable(T)(可为空)、Optional.empty()
  • 获取:orElse(有值返值无返默认)、orElseGet(懒加载默认)、orElseThrow(抛异常)
  • 链式:map/flatMap/filter/ifPresent

十一、JVM 基础

11.1 内存模型(JDK8+)

区域

线程

内容

程序计数器

私有

当前线程执行字节码行号

虚拟机栈

私有

栈帧(局部变量表/操作数栈/返回地址)

本地方法栈

私有

Native方法调用

堆(Heap)

共享

对象实例,GC主要区域。新生代(Eden+S0+S1)+老年代

方法区(元空间)

共享

类信息/常量/静态变量/JIT编译缓存。JDK8+使用本地内存(元空间 Metaspace),替代PermGen

运行时常量池

共享

Class文件常量池运行时表示(在元空间内)

11.2 类加载

  • 过程:加载 → 验证 → 准备(static变量赋默认值)→ 解析(符号引用→直接引用)→ 初始化(static变量赋值+static代码块,clinit方法)
  • 双亲委派:加载请求先委派父类加载器(Bootstrap→Extension/Platform→Application→自定义)→父加载不了才自己加载。避免核心类被篡改(如自定义java.lang.String)
  • 破坏双亲委派:Tomcat(每个WebApp独立加载)、JDBC(SPI机制,ThreadContextClassLoader)

11.3 GC算法与垃圾回收器

判断对象存活

  • 引用计数法:有循环引用问题(Java不用)
  • 可达性分析:GC Roots(栈引用、static引用、JNI引用等)→ 引用链上对象存活,不可达对象判断为垃圾

四种引用类型

引用

回收时机

强引用(Strong)

永不回收(除非不可达)

软引用(SoftReference)

内存不足时回收(适合缓存)

弱引用(WeakReference)

下次GC即回收(ThreadLocal的key)

虚引用(PhantomReference)

回收时收到通知(管理堆外内存,如NIO DirectByteBuffer)

GC算法

  • 标记-清除:标记存活→清除未标记。内存碎片
  • 标记-整理:标记存活→移动到一端。无碎片但耗时长(老年代用)
  • 复制:Eden+S0→S1,存活率低时高效(新生代用)
  • 分代收集:新生代用复制算法(Minor GC),老年代用标记-整理/清除(Full GC)

垃圾回收器

回收器

算法

特点

Serial / Serial Old

复制 / 标记-整理

单线程,Client模式默认

Parallel / Parallel Old

复制 / 标记-整理

多线程并行,JDK8默认,关注吞吐量

ParNew

复制

Serial多线程版,配合CMS

CMS

标记-清除

并发低停顿(4步骤:初始标记→并发标记→重新标记→并发清除)。CPU敏感、碎片、浮动垃圾,JDK14移除

G1(JDK9+默认)

标记-整理+复制

Region分区,可预测停顿。Mixed GC

ZGC(JDK11+)

染色指针+读屏障

超低延迟(<1ms停顿),TB级堆。JDK15+生产可用,分代ZGC(JDK21+)

Shenandoah(JDK12+)

转发指针+读屏障

低延迟,并发整理

11.4 JVM调优参数

参数

说明

-Xms / -Xmx

堆初始大小 / 堆最大大小(通常设相等,避免扩容)

-Xss

线程栈大小

-Xmn / -XX:NewRatio

新生代大小 / 老新比例

-XX:SurvivorRatio

Eden:S0:S1比例

-XX:MetaspaceSize / -XX:MaxMetaspaceSize

元空间初始/最大(JDK8+)

-XX:+UseG1GC / -XX:+UseZGC

选择GC算法

-XX:MaxGCPauseMillis

最大GC停顿时间目标(G1)

-XX:+PrintGCDetails

打印GC日志

-XX:+HeapDumpOnOutOfMemoryError

OOM时生成堆dump


总结:JavaSE是Java开发的基石,核心掌握面向对象(封装继承多态)、集合框架(HashMap/ConcurrentHashMap原理)、多线程(synchronized锁升级/AQS/线程池)、JVM内存模型与GC、JDK8新特性(Lambda/Stream/Optional)。面试高频考点已在上方标注 ⚠️ 和 ❗。