背景知识
先理清几个基本概念。Ja va有三个版本:Ja vaSE是标准版,用来开发桌面应用;Ja vaEE是企业版,支撑企业级应用;Ja vaME是微型版,面向嵌入式设备和移动设备。这三个版本分别对应不同场景,但核心语法都是相通的。
编译与运行是Ja va程序的两大阶段。编译时,我们用ja vac.exe工具把.ja va源文件编译成.class字节码文件。命令很简单:ja vac 文件名.ja va,如果需要指定编译后存放路径,可以加上-d参数。运行阶段,用ja va.exe执行.class文件,注意命令后面跟的是类名,不带.class后缀。这一切都依托于JVM(Ja va虚拟机),它在运行时负责解释执行字节码。
开发环境方面,JDK(Ja va开发工具包)包含了编译器、调试器等全套工具;JRE(Ja va运行环境)只包含JVM和运行所需的库;而JVM就是那个执行字节码的虚拟机。三者关系是:JDK包含JRE,JRE包含JVM。
工具与格式里有个小工具native2ascii,用于将Unicode字符转成u开头的ASCII表示。UML(统一建模语言)则用于面向对象设计,其中的箭头含义:空心箭头指向父类(继承),空心虚线箭头指向接口(实现),实心实线箭头表示关联关系。
注释有三种://单行注释,/* */多行注释,/** */文档注释(用于生成帮助文档)。
类与方法结构的基本框架如下:
类体 {
方法体 {
ja va语句;
}
}
总结一下:Ja vaSE是基础,Ja vaEE是企业版,Ja vaME是微型版;编译用ja vac,运行用ja va;JDK是开发工具包,JRE是运行环境,JVM是虚拟机;UML用来画设计图,注释用来写说明。类和方法的结构就是上面那个样子。
一、集成开发环境(IDEA)
IDEA是Ja va开发中最常用的IDE之一,下面整理一下它的组织方式和常用快捷键。
组织方式
IDEA的工程结构分为三层:Project(工程)是最高层级,包含多个模块;Module(模块)是工程下的子模块,包含多个包;Package(包)是模块下的子包,用于组织类和资源。
字体设置
路径:File -> Settings -> Font,可以调整编辑器的字体样式和大小。
快捷键分类总结
导航与操作
- 展开/移动列表:左右箭头展开或折叠列表,上下箭头在列表中移动。
- 切换与定位:
Alt+左右箭头切换Ja va程序,Alt+上下箭头在方法间快速移动,Alt+标号打开标号窗口,Ctrl+G定位到某一行,Ctrl+点击切换源码,Ctrl+H查看实现类。 - 查找与搜索:
Ctrl+Shift+N查找文件,Ctrl+N查找类文件,Ctrl+F12在当前类中查找方法。
编辑与格式化
- 代码编辑:
Ctrl+Y删除一行,Shift+F6重命名,Alt+拖动一次编辑多行,Ctrl+Alt+T将选中代码放在TRY{}、IF{}、ELSE{}中。 - 代码提示与自动补全:
Ctrl+空格代码提示,Ctrl+P方法参数提示,Ctrl+J自动代码,Ctrl+Alt+Space类名或接口名提示。 - 格式化与优化:
Ctrl+Alt+L格式化代码,Ctrl+Alt+I自动缩进,Ctrl+Alt+O优化导入的类和包。
运行与纠错
- 运行程序:
Ctrl+Shift+F10运行当前程序。 - 纠错与提示:
Alt+回车纠错提示。
窗口操作
- 全屏模式:
Ctrl+Shift+F12切换全屏。
总结
工程-模块-包的三层结构清晰明了,便于管理。快捷键方面,导航与查找能快速定位,编辑与格式化提高编写效率,运行与纠错帮你快速调试,窗口操作优化布局。熟练掌握这些快捷键,开发效率能上一个大台阶。
二、JVM内存划分
JVM的内存区域是理解Ja va程序运行机制的关键。局部变量在方法体中声明,运行时在栈中分配内存。方法区内存最早有数据——类加载时字节码文件就被放到方法区,调用方法时再在栈内分配空间。堆内存用来存放new出来的对象,成员变量中的实例变量(每个对象一份)就存储在对象内部,只能通过引用来操作。栈内存存储局部变量,栈帧永远指向栈顶,先进后出,后进先出。

内存区域与数据存储
- 堆内存(Heap):存储实例变量(对象属性)。每个JVM实例只有一个堆,所有线程共享。垃圾回收器(GC)主要针对堆内存进行回收。
- 方法区(Method Area):存储静态变量(类变量)和类元数据(类信息、常量池等)。每个JVM实例只有一个方法区,所有线程共享。方法区是最先有数据的内存区域,因为类加载时静态变量和类信息会初始化。
- 栈内存(Stack):存储局部变量和方法调用栈帧。每个线程有一个独立的栈,线程私有。栈内存使用最频繁,因为方法调用和局部变量的生命周期短。
变量存储位置
- 局部变量:存储在栈内存中,生命周期与方法调用一致,方法结束时销毁。
- 实例变量:存储在堆内存中,生命周期与对象一致,对象被垃圾回收时销毁。
- 静态变量:存储在方法区中,生命周期与类一致,类卸载时销毁。
垃圾回收器(GC)
GC主要针对堆内存,清理不再使用的对象。栈内存和方法区的垃圾回收机制与堆不同,但效率更高,因为它们的生命周期短且数据量小。
三、关键字
类与关键字
public:表示公开的类,类名必须与文件名一致,一个文件中只能有一个public类。class:用于定义类。static:表示静态的,修饰的成员变量或方法属于类级别,不依赖于对象。静态变量在类加载时初始化,存储在方法区。静态方法不能访问实例变量或实例方法,需要通过对象访问。break:跳出循环或switch语句。continue:跳过当前循环剩余部分,直接进入下一次循环。语法:continue 循环名称;或配合循环名称:使用。this:表示当前对象的引用,用于区分局部变量和实例变量,或在构造方法中调用其他构造方法(this(实参))。不能用于静态方法中。native:调用JVM本地程序。
输入与输出
System.out.println():控制台输出并换行。- 键盘输入:创建
ja va.util.Scanner对象,如Scanner s = new Scanner(System.in);,然后s.next()读取字符串,s.nextInt()读取整数。
final关键字
- 修饰类:类不能被继承。
- 修饰方法:方法不能被重写。
- 修饰变量:变量不能被修改。修饰的成员变量必须手动赋值。修饰的引用一旦指向一个对象,就不能指向其他对象,但所指向的对象内部可以修改。
- 常量:
public static final 类型 常量名 = 值;,命名全部大写,用下划线分隔。
super关键字
- 代表当前对象的父类型特征,用于访问父类的属性、方法或调用父类的构造方法。
- 语法:
super.访问属性/方法,super()调用父类构造方法。 - 不能用于静态方法中。如果父类和子类有同名属性,访问父类属性时不能省略
super。构造方法第一行如果没有this()或super(),默认会调用super()。
static关键字
- 静态变量:类级别,类加载时初始化。
- 静态方法:类级别,不能访问实例变量或实例方法。
- 静态代码块:类加载时执行,只执行一次。语法:
static {}。 - 实例代码块:在构造方法执行之前执行,用于对象初始化。
包与导入
package:用于管理类,命名规则:公司域名倒序.项目名.模块名.功能名。语法:package 包名;。import:导入包中的类。语法:import 包名.类名;或import 包名.*;。ja va.lang.*是核心语言包,无需导入。- 快捷键:
Ctrl+Shift+O自动导入。
访问控制权限修饰符
private:私有,只能在本类中访问。default:默认,可以被本包中的其他类访问。protected:受保护,可以被本包及不同包的子类访问。public:公共,任何地方都可以访问。- 类只能使用
public或默认修饰符(缺省),内部类除外。
总结
- 类与关键字:
public、class、static、this、super等的作用与用法。 - 输入与输出:控制台输出与键盘输入的基本操作。
final:用于修饰类、方法、变量,表示不可修改。static:修饰类级别的成员,与对象无关。- 包与导入:
package和import的使用及命名规则。 - 访问控制权限:
private、default、protected、public的访问范围。
四、Ja va基础
标识符
标识符是用户有权命名的单词,包括类名、方法名、常量名、变量名、接口名等。命名规则:类名、接口名采用大驼峰(首字母大写,后面每个单词首字母大写);方法名、变量名采用小驼峰(首字母小写,后面每个单词首字母大写);常量名全部大写,单词间用下划线分隔。
字面值
字面值就是数据本身,比如数字、字符串,在IDE中通常以紫色显示。
变量
- 局部变量:定义在方法体内,没有默认值,必须手动初始化,生命周期与方法调用一致。
- 成员变量:定义在类体内,有默认值(数值类型为0,布尔类型为
false,引用类型为null)。分为实例变量和静态变量。 - 实例变量:不带
static,属于对象级别,必须通过对象引用访问(引用.变量名),存储在堆内存中。 - 静态变量:带
static,属于类级别,类加载时初始化,存储在方法区,通过类名访问(类名.变量名)。
引用
引用是一个变量,可以是实例变量或局部变量。实例变量:类名 引用 = new 类名();;局部变量:引用 变量名 = new 引用();。
数据类型
- 基本数据类型:整数型
byte(1字节)、short(2字节)、int(4字节)、long(8字节,后缀L);浮点型float(4字节)、double(8字节);布尔型boolean(1字节);字符型char(2字节)。 - 引用数据类型:
String不可变,存储在方法区字符串池中。 - 比较:基本数据类型用
==;引用数据类型(包括String)用equals。
字符编码
发展顺序:ASCII < ISO-8859-1 < GB2312 < GBK < GB18030 < Big5 < Unicode。
位运算符
- 逻辑异或(^):两边不一样为真。
- 短路与(&&):左边为假时直接返回假。
- 按位与(&):将操作数转换为二进制后按位与。
- 短路或(||):左边为真时直接返回真。
- 左移(<<):相当于乘以2的N次方。
- 右移:带符号右移(>>)正数用0填充,负数用1填充;无符号右移(>>>)无论正负都用0填充。
- 按位取反(~):结果为
-(n+1)。
方法(函数)
定义格式:[修饰符列表] 返回值类型 方法名(形参列表) { 方法体; return; }。调用:类名.方法名(实参列表);。实例方法不带static,需要对象参与;静态方法带static,与对象无关。
方法重载(Overload)
在同一类中,方法名相同但参数列表不同,与返回值类型和修饰符列表无关。
方法递归
方法调用自身,每次递归都会压栈,分配新的内存空间。示例:
public static int sum(int n) {
if (n == 1) {
return 1;
}
return n + sum(n - 1);
}

方法覆盖(Override)
发生在继承关系中,子类重写父类方法。方法名、返回值类型、形参列表必须一致,访问权限不能比父类更低,抛出异常不能更多。私有方法、构造方法不能覆盖,静态方法不存在覆盖。
总结
- 标识符:命名规则与用途。
- 变量:局部变量、实例变量、静态变量的定义与存储位置。
- 数据类型:基本数据类型与引用数据类型的区别。
- 位运算符:各种位运算符的作用与用法。
- 方法:定义、调用、重载、递归与覆盖的规则与特点。
五、Ja va 控制流与 Lambda 表达式
1.控制流语句
- If-Else:条件判断。
- Switch:多分支选择,记得加
break。 - For循环:
for(初始表达式; 布尔表达式; 更新循环体)。 - 增强For循环(For Each):
for(元素类型 变量名 : 数组或集合)。 - While循环:先判断后执行。
- Do-While循环:先执行一次再判断。
2.Ja va 标签
标签用于控制嵌套循环的跳转。语法:label:。用法:continue label;跳过当前循环继续执行标签处的循环;break label;结束标签处的循环。
3.Lambda 表达式
Lambda让代码更简洁,尤其在实现函数式接口时。下面是一些常见场景:
- 实现 Runnable:
new Thread(() -> System.out.println("...")).start(); - 事件处理:
show.addActionListener((e) -> { ... }); - 列表迭代:
features.forEach(n -> System.out.println(n));或使用方法引用System.out::println。 - Map 和 Reduce:
costBeforeTax.stream().map((cost) -> cost + .12*cost).reduce((sum, cost) -> sum + cost).get(); - 对列表每个元素应用函数:
G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", ")); - 计算集合元素的最大值、最小值、总和、平均值:使用
IntSummaryStatistics。
总结
- 控制流语句:控制程序执行流程。
- Ja va标签:控制嵌套循环的跳转。
- Lambda表达式:简化匿名类,代码更简洁。
- Stream API:提供强大的集合操作功能,如
map、reduce、forEach等。
六、面向对象
面向过程与面向对象的对比
- 面向过程:关注问题的具体步骤和流程,耦合度高,扩展性差。
- 面向对象:将问题分解为对象,每个对象负责特定功能,耦合度低,关注对象功能。三大特征:封装、继承、多态。
面向对象的分析与设计
- OOA:分析问题域,识别对象及其关系。
- OOD:设计对象的结构和行为,定义类及其关系。
- OOP:使用编程语言实现设计,创建对象并实现功能。
类与对象
- 类:高度抽象的对象集合,是一个模板。包含静态代码块、实例代码块、静态变量、实例变量、构造方法、静态方法、实例方法、成员变量、成员方法。
- 对象:类的具体实例,通过
new创建。引用保存了对象的地址,指向堆内存中的对象。
User u = new User(); Address a = new Address(); u.addr = a; Print(u.addr.city); A.city = "天津"; Print(u.addr.city);

封装
私有化属性(private),通过getter和setter提供操作入口,可以在setter中添加业务逻辑进行安全控制。
构造方法
用于创建对象并初始化实例变量。语法:修饰符 构造方法名(形参) { 构造方法体; }。没有返回值类型,方法名与类名一致。如果没有定义构造方法,编译器会生成一个无参的缺省构造器。
继承
语法:class 子类名 extends 父类名。Ja va中类只能单继承。父类也叫基类、超类,子类也叫派生类。私有的属性和方法、构造方法不能被继承。通过继承链,子类可以间接继承父类的父类。如果没有显式继承,默认继承ja va.lang.Object。super关键字用于调用父类的属性、方法和构造方法。
多态
- 向上转型:子类转换为父类型,自动转换。语法:
父类 引用 = new 子类(); - 向下转型:父类转换为子类,强制转换。语法:
子类 引用 = (子类) 父类引用;,存在ClassCastException风险。 - 动态绑定:父类型引用指向子类型对象,调用方法时实际执行子类的方法。
- instanceof运算符:在强制转换前检查对象类型,避免异常。
抽象类
使用abstract修饰,属于引用数据类型。不能使用private或final修饰。可以包含抽象方法和非抽象方法。不能实例化,但可以有构造方法供子类使用。抽象方法没有方法体,包含抽象方法的类一定是抽象类。非抽象类继承抽象类时,必须实现所有抽象方法。
接口
使用interface定义,是完全抽象的(特殊的抽象类)。只能包含常量和抽象方法(默认public static final和public abstract,可省略)。支持多继承,一个接口可以继承多个接口。类通过implements实现接口,一个类可以实现多个接口。接口支持多态,用于解耦合。
抽象类与接口的区别
| 特性 | 抽象类 | 接口 |
|---|---|---|
| 抽象程度 | 半抽象(可以包含具体方法) | 完全抽象(只能包含抽象方法) |
| 构造方法 | 有构造方法,供子类使用 | 无构造方法 |
| 继承 | 单继承 | 支持多继承 |
| 内容 | 可以包含抽象方法和非抽象方法 | 只能包含常量和抽象方法 |
| 用途 | 抽象行为和数据 | 主要抽象行为 |
| 实例化 | 不能实例化 | 不能实例化 |
开发中的选择
- 抽象类:多个类有共同属性和行为,且需要部分具体实现时使用,适合定义“是什么”(is-a关系)。
- 接口:需要定义一组行为规范,不关心具体实现时使用,适合定义“能做什么”(like-a关系)。
示例
abstract class Animal {
abstract void sound();
void sleep() { System.out.println("Sleeping..."); }
}
interface Flyable {
void fly();
}
class Bird extends Animal implements Flyable {
void sound() { System.out.println("Chirp..."); }
public void fly() { System.out.println("Flying..."); }
}
总结
- 面向对象通过封装、继承和多态提高代码复用性、扩展性和维护性。
- 类与对象是基础,封装增强安全性和可控性,继承实现代码复用并支持多态,多态降低耦合度。
- 面向抽象编程,进一步降低耦合度。
- 抽象类用于定义共有特征,接口用于定义行为规范。根据需求选择。
七、类库
源码、字节码与帮助文档
- 源码:理解程序逻辑。
- 字节码:编译后的中间代码,由JVM执行,跨平台。
- 帮助文档:通过
ja vadoc生成,注意版本要与代码一致。
Object类(根类)
protected Object clone():对象克隆。boolean equals(Object obj):判断对象是否相等,默认比较引用地址,通常需要重写。int hashCode():返回哈希码,用于哈希表。String toString():返回字符串表示,默认返回类名@哈希值,通常需要重写。protected void finalize() throws Throwable:垃圾回收前调用,用于清理。System.gc():建议启动垃圾回收器,但不保证立即执行。
System类
System.gc():建议垃圾回收。System.out:控制台输出。System.currentTimeMillis():获取自1970-01-01 00:00:00到当前时间的毫秒数。System.exit(0):退出JVM。
Arrays类
Arrays.sort(arr):排序。Arrays.binarySearch(arr, key):二分查找,不存在返回-1。
String类
构造方法:String(byte[])、String(char[])、String(String)。常用方法:charAt、compareTo、contains、endsWith、startsWith、equals、equalsIgnoreCase、getBytes、indexOf、lastIndexOf、isEmpty、replace、substring、toCharArray、toLowerCase、toUpperCase、split、trim、valueOf。
StringBuffer与StringBuilder
StringBuffer:线程安全,适用于多线程。StringBuilder:非线程安全,性能更优。
包装类
将基本数据类型转换为对象,如Integer、Character。常用方法:intValue()拆箱,parseInt(String)字符串转整数。

日期相关类
ja va.util.Date:表示日期和时间。SimpleDateFormat:格式化日期,提供format()和parse()。
数字相关类
DecimalFormat:格式化数字。BigDecimal:高精度计算,适用于财务。Random:生成随机数。
枚举(Enum)
定义一组常量:enum Season { SPRING, SUMMER, AUTUMN, WINTER }
内部类
- 成员内部类:定义在类中,可访问外部类所有成员。
- 局部内部类:定义在方法中,只能在该方法内访问。
- 静态内部类:
static修饰,只能访问外部类静态成员。 - 匿名内部类:没有名称,通常用于实现接口或抽象类。
总结
- 源码理解程序,字节码跨平台运行,帮助文档指导开发。
- Object是根类,提供基本操作。
- System提供系统级操作。
- String处理字符串,StringBuffer/StringBuilder用于拼接,包装类将基本类型转为对象,日期类处理时间,内部类灵活组织代码。
八、数组
一维数组
- 数组是引用数据类型,存储在堆内存中。可以存储各种数据类型,但不能直接存储对象,存储的是对象的引用。
- 优点:查询效率极高(内存连续,类型相同)。缺点:随机增删效率低,不能存储大数据量。
- 静态初始化:
数据类型[] 数组名 = {元素1, 元素2, ...};;动态初始化:数据类型[] 数组名 = new 数据类型[长度];。 - 遍历:
for循环或增强for循环。 - 数组作为方法参数,
main方法的参数是字符串数组。 - 数组扩容:新建大数组,用
System.arraycopy拷贝。
二维数组
- 二维数组是数组的数组,可以看作表格。静态初始化:
数据类型[][] 数组名 = {{元素1, 元素2}, {元素3, 元素4}};;动态初始化:数据类型[][] 数组名 = new 数据类型[行数][列数];。 - 遍历:嵌套
for循环。
总结
- 一维数组适合存储一组相同类型数据,查询效率高;二维数组适合表格型数据。
- 数组应用场景:固定长度数据、存储对象引用、表格数据。
九、算法
排序算法
- 冒泡排序:重复遍历,相邻比较交换。时间复杂度O(n²)。
- 选择排序:每次选最小放到已排序末尾。O(n²)。
- 插入排序:将未排序元素插入到已排序正确位置。O(n²),适合部分有序数据。
- 快速排序:选基准,分左右递归。O(n log n),高效。
- 归并排序:分治后合并。O(n log n),稳定。
查找算法
- 线性查找:遍历,O(n)。
- 二分查找:有序数组,每次取中间。O(log n)。
总结
- 排序算法选择依据:数据规模、是否有序、稳定性要求。
- 查找算法:无序用线性,有序用二分。
十、异常
1. 异常的基本概念
- 异常以类的方式存在,每个异常类都可以创建对象。
- 方法覆盖时,子类不能抛出比父类方法更高的异常(运行时异常除外)。
- 异常分类:
Throwable分为Error(系统级错误,不可处理)和Exception(异常,运行阶段发生)。Exception又分为编译时异常(受检异常)和RuntimeException(运行时异常)。
2. 常见运行时异常
NullPointerException:空指针。ArrayIndexOutOfBoundsException:数组下标越界。ClassCastException:类型转换异常。NumberFormatException:数字格式异常。
3. 异常处理方式
throws:在方法声明处抛出,由调用者处理。try-catch-finally:捕获并处理,finally无论是否发生异常都会执行,常用于释放资源。
4. 常用异常方法
getMessage():获取简单描述信息。printStackTrace():打印堆栈追踪信息。
5. 自定义异常
- 继承
Exception或RuntimeException,提供无参和有参构造方法,使用throw手动抛出。
6. 异常处理的最佳实践
- 捕获具体异常,合理使用
finally,避免空指针,记录日志。
总结
- 异常分类:
Error和Exception,Exception分编译时和运行时。 - 处理方式:
throws或try-catch-finally。 - 自定义异常:继承异常类,提供构造方法,
throw抛出。
十一、I/O
I/O概述
I/O(输入/输出)是应用程序与外部设备的数据交互。Ja va通过ja va.io包提供丰富的类库,支持文件操作、字节流、字符流等。
File类
File是唯一代表磁盘文件本身的对象。构造方法:File(String path)、File(String parent, String child)、File(File parent, String child)。常用方法:exists()、delete()、createNewFile()、getName()、getPath()、getAbsolutePath()、canRead()、canWrite()、isFile()、isDirectory()、length()、list()、listFiles()、createTempFile()、deleteOnExit()。
字节流
字节流用于处理二进制数据。InputStream是字节输入流抽象类,OutputStream是字节输出流抽象类。常用实现类:FileInputStream、FileOutputStream。读写方法:read()、read(byte[])、write(int)、write(byte[])、flush()、close()。

字符流
字符流用于处理文本数据,以字符为单位,支持字符编码。Reader和Writer是抽象基类。常用实现类:FileReader、FileWriter、BufferedReader(提供readLine())、BufferedWriter(提供newLine())、InputStreamReader、OutputStreamWriter(支持指定编码)。
字符流与字节流的区别
- 字节流以字节为单位,适合二进制数据;字符流以字符为单位,适合文本数据,支持编码。
- 字符流通常与缓冲区结合使用,提高效率。
总结
- File类操作文件和目录。
- 字节流处理二进制,字符流处理文本,注意编码。
- 使用缓冲区提高性能,用
try-with-resources确保流关闭。
十二、集合
集合的特点
集合是存储一组对象的容器,存储的是对象的内存地址。不同的集合对应不同的数据结构,所有集合类都在ja va.util包中。
集合的层次结构
Iterable:所有集合可迭代。Collection:存储单个元素的父接口,子接口包括List、Set、Queue。Map:存储键值对,独立于Collection。
常用实现类
- List:有序可重复。
ArrayList(数组,查询快)、LinkedList(双向链表,增删快)、Vector(线程安全,效率低)。 - Set:无序不可重复。
HashSet(底层HashMap)、TreeSet(底层TreeMap,可排序)。 - Map:
HashMap(哈希表,非线程安全)、Hashtable(线程安全,效率低)、Properties(key/value均为String)、TreeMap(二叉树,key排序)。
集合的选择
- 单个元素:有序允许重复用List,查询多选ArrayList,增删多选LinkedList;不需要重复用Set,无序选HashSet,有序选TreeSet。
- 键值对:非线程安全用HashMap,线程安全用Hashtable或Properties,需要排序用TreeMap。
总结
- List有序可重复,Set无序不可重复,Map存储键值对。
- 根据需求选择合适的集合,注意线程安全。
十三、泛型
1. 泛型概述
泛型是JDK 5.0引入的新特性,用于统一集合中元素的类型,只在编译阶段起作用,编译后类型擦除。语法:List
2. 优点与缺点
- 优点:类型安全,代码复用,代码简洁。
- 缺点:导致集合存储缺少多样性,类型擦除。
3. 自动推断机制(钻石表达式)
JDK 7开始,后面的泛型类型可以省略:List
4. 自定义泛型
- 泛型类:
public class Box{ ... } - 泛型方法:
publicvoid printArray(T[] array) { ... }
5. 通配符
>:任意类型。extends T>:T或其子类型(上界)。super T>:T或其父类型(下界)。
6. 限制
- 不能使用基本类型,不能创建泛型数组,不能实例化泛型类型。
总结
- 泛型提高安全性和复用性,钻石表达式简化代码,通配符提供灵活约束。
十四、多线程
进程是应用程序,线程是进程中的执行单元。并行是多个CPU同时执行,并发是单个CPU交替执行。
线程状态转换

- 新建状态(New)→ 就绪状态(Runnable)→ 运行状态(Running)→ 阻塞状态(Blocked)→ 就绪状态 → 运行状态 → 死亡状态(Dead)。
- 阻塞分三种:等待阻塞(wait)、同步阻塞(锁被占用)、其他阻塞(sleep、join、I/O)。
实现线程的三种方式
- 继承Thread类:简单,但受单继承限制。
- 实现Runnable接口:灵活,避免单继承限制。
- 使用Callable和Future:可以获取线程执行结果,支持异常处理。
线程常用方法
currentThread()、getName()、setName()、sleep()、interrupt()、yield()、join()、setPriority()等。
线程安全问题
多线程并发、有共享数据、有修改行为时会产生线程安全问题。解决方案:线程同步(排队执行),使用synchronized关键字。
死锁
死锁是多个线程互相等待对方释放锁,导致无法继续执行。四个必要条件:互斥、占有并等待、不可抢占、循环等待。避免死锁:避免嵌套锁、按顺序获取锁、使用超时机制。
守护线程
守护线程依赖用户线程,当所有用户线程结束时自动退出。典型代表:垃圾回收线程。通过setDaemon(true)设置,必须在start()之前。
定时器
ja va.util.Timer用于间隔特定时间执行任务。实际开发中更多使用Spring Task框架。
wait()和notify()
wait()让当前线程等待并释放锁,notify()唤醒等待线程。它们必须在同步块中调用,是Object类的方法。
生产者消费者模式
生产线程和消费线程通过wait()和notify()实现均衡。典型应用:仓库最多存储一个元素,生产一个消费一个。

十五、反射
1. Class 对象
每个类加载到内存时都会生成一个Class对象,存储了类的所有信息。反射通过Class对象在运行时动态获取类的信息并操作成员。
2. 生成方式
类名.class:不进行初始化。Class.forName("包名.类名"):默认静态初始化。Class.forName("包名.类名", false, 类加载器):可控制是否初始化。实例对象.getClass():运行时实际对象所属类。
3. 常用方法
getName()、getSuperclass()、getInterfaces()、isArray()、isEnum()、isInterface()、isPrimitive()、asSubclass()等。
4. 静态加载与动态加载
- 静态加载:
new ClassName(),编译时必须提供类定义。 - 动态加载:
Class.forName(),编译时可以缺席,运行时按需提供。
总结
- Class对象是反射的核心,三种生成方式,常用方法包括
getName()、asSubclass()等。 - 动态加载提高了灵活性。
十六、小游戏(进击的小鸟)
这是一个完整的Ja va小游戏项目,包含多个类:StartGame(游戏入口)、BirdGame(主面板,负责绘制和逻辑)、Bird(小鸟类)、Column(管道类)、Ground(地面类)、Music(音乐播放)、Score(分数实体)、ScoreManager(JDBC连接数据库操作)。游戏通过鼠标控制小鸟飞行,躲避管道,得分并记录到数据库。代码结构清晰,适合初学者练习面向对象、多线程和数据库操作。
十七、Stream
Stream简介
Ja va 8引入的Stream API是对集合功能的增强,专注于高效的聚合操作,与Lambda表达式结合极大提高编程效率和可读性。
Stream原理
将元素集合看作流,在管道中传输,经过中间操作(如筛选、排序、聚合)后由最终操作得到结果。
Stream优点
- 速度更快,代码更少,强大的API,便于并行,减少空指针异常(Optional)。
操作三步
- 创建Stream(数据源)
- 中间操作链(处理数据)
- 终止操作(产生结果)
中间操作
filter:过滤元素。map:转换元素。flatMap:将数组或Collection元素展平。distinct:去重。sorted:排序。peek:消费元素(中间操作,需配合最终操作执行)。limit:取前n个。skip:跳过前n个。
终端操作
forEach、forEachOrdered:遍历。toArray:转数组。reduce:聚合。collect:转集合。min、max、count:统计。
总结
- Stream API让集合操作更简洁高效,配合Lambda表达式,是Ja va 8的亮点。