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(拒绝策略)
- 执行流程:任务来 → 核心线程数未满则创建核心线程 → 已满则入队 → 队列满则创建非核心线程(上限maximumPoolSize) → 还满则执行拒绝策略
- 4种拒绝策略:AbortPolicy(抛异常,默认)、CallerRunsPolicy(调用者线程执行)、DiscardPolicy(直接丢弃)、DiscardOldestPolicy(丢弃队首)
- 常见线程池: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)。面试高频考点已在上方标注 ⚠️ 和 ❗。