第1章 Java程序设计概述
Java语言的特点
- 平台无关性:一次编写,到处运行(Write Once, Run Anywhere),通过JVM实现
- 面向对象:支持封装、继承、多态三大特性
- 安全性:强类型检查、自动内存管理(垃圾回收)、字节码验证
- 健壮性:异常处理机制、自动内存管理
- 多线程:内置对并发编程的支持
Java体系结构
- Java虚拟机(JVM):执行字节码的虚拟计算机,实现平台无关性
- Java运行时环境(JRE):包括JVM和核心类库
- Java开发工具包(JDK):包括JRE和开发工具(编译器、调试器等)
第2章 Java程序设计环境
第一个Java程序
|
|
- 编译:
javac HelloWorld.java,生成HelloWorld.class字节码文件 - 运行:
java HelloWorld
Java程序结构
- 源文件命名:必须与公共类名相同,以
.java结尾 - 类定义:使用
class关键字,可包含属性和方法 - 主方法:
public static void main(String[] args),程序入口点
第3章 Java的基本程序设计结构
数据类型
1. 基本数据类型(8种):
| 类型 | 大小 | 范围 | 默认值 |
|---|---|---|---|
| 整数类型 | |||
| byte | 1字节 | -128 ~ 127 | 0 |
| short | 2字节 | -32768 ~ 32767 | 0 |
| int | 4字节 | -2147483648 ~ 2147483647 | 0 |
| long | 8字节 | 很大 | 0L |
| 浮点类型 | |||
| float | 4字节 | 约±3.4×10^38 | 0.0f |
| double | 8字节 | 约±1.8×10^308 | 0.0 |
| 字符类型 | |||
| char | 2字节 | 0 ~ 65535(Unicode) | ‘\u0000’ |
| 布尔类型 | |||
| boolean | 1位 | true/false | false |
注:Java是强类型语言,变量必须声明类型后才能使用
2. 引用数据类型:
- 类、接口、数组、字符串等
- 默认值为
null
变量与常量
-
变量声明:
type identifier [=value];1 2int age = 25; double salary = 5000.0; -
常量:使用
final关键字修饰,必须初始化且值不可变1final double PI = 3.1415926; -
类常量:使用
static final修饰,属于类而非对象1public static final int MAX_SIZE = 100;
运算符与表达式
1. 算术运算符:
+、-、*、/、%(取余)++(自增)、--(自减)可前置或后置
2. 关系运算符:
>、<、>=、<=、==、!=,结果为boolean类型
3. 逻辑运算符:
&&(逻辑与)、||(逻辑或)、!(逻辑非)- 具有短路特性:
(a && b)中,若a为false,则b不会计算
4. 位运算符:
&(按位与)、|(按位或)、^(按位异或)、~(按位取反)<<(左移)、>>(右移)、>>>(无符号右移)
5. 赋值运算符:
=、+=、-=、*=、/=、%=等
6. 字符串连接:
-
使用
+运算符连接字符串和其他类型,会自动转换为字符串1 2 3String name = "Alice"; int age = 30; System.out.println("Name: " + name + ", Age: " + age); // Name: Alice, Age: 30
流程控制结构
1. 条件语句:
-
if-else:
1 2 3 4 5if (condition) { // 条件为true时执行 } else { // 条件为false时执行 } -
多重条件:
1 2 3 4 5 6 7if (condition1) { // ... } else if (condition2) { // ... } else { // ... } -
switch-case:支持
byte、short、int、char、String和enum类型1 2 3 4 5 6 7 8 9 10switch (expression) { case value1: // 执行代码 break; case value2: // 执行代码 break; default: // 所有case都不匹配时执行 }
2. 循环语句:
-
for循环:
1 2 3for (initialization; condition; update) { // 循环体 }增强for循环(用于遍历集合或数组):
1 2 3for (type element : collection/array) { // 操作element } -
while循环:
1 2 3while (condition) { // 循环体 } -
do-while循环:
1 2 3do { // 循环体 } while (condition);
数组
1. 数组声明与初始化:
|
|
2. 数组特性:
- 长度固定,一旦创建不可改变
- 元素类型必须一致
- 通过索引访问(从0开始)
- 数组对象有
length属性获取长度
3. 数组操作:
-
遍历数组:
1 2 3for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); }或使用增强for循环:
1 2 3for (int num : numbers) { System.out.println(num); }
第4章 对象与类
面向对象编程基础
1. 类与对象:
- 类:对象的模板,定义属性和方法
- 对象:类的实例,通过
new关键字创建
2. 面向对象三大特性:
- 封装:将数据和操作封装在类中,通过访问控制限制外部直接访问
- 继承:子类继承父类的属性和方法,实现代码重用
- 多态:同一方法在不同对象上表现出不同行为
类的定义与使用
1. 类定义语法:
|
|
2. 成员变量:
- 实例变量:属于对象,每个对象独立拥有
- 静态变量(类变量):使用
static修饰,属于类,所有对象共享
3. 方法:
- 实例方法:可访问实例变量和静态变量
- 静态方法:使用
static修饰,只能访问静态变量,通过类名直接调用
4. 对象创建与使用:
|
|
访问控制
Java提供四种访问控制级别,按可见范围从大到小排列:
| 修饰符 | 类内部 | 同包 | 子类(不同包) | 其他包 |
|---|---|---|---|---|
| public | ✓ | ✓ | ✓ | ✓ |
| protected | ✓ | ✓ | ✓ | ✗ |
| 默认(无修饰符) | ✓ | ✓ | ✗ | ✗ |
| private | ✓ | ✗ | ✗ | ✗ |
注:类只能使用public或默认修饰符
构造方法
- 特点:
- 方法名与类名相同
- 无返回类型(连
void也没有) - 用于对象初始化
1. 默认构造方法:
- 若类没有显式定义任何构造方法,编译器会自动生成一个无参构造方法
- 若已定义任何构造方法,则不会自动生成
2. 构造方法重载:
- 多个构造方法,参数列表不同(参数个数、类型或顺序不同)
- 调用时根据实参类型和数量匹配相应构造方法
3. 构造方法调用:
- 使用
this([参数])调用同一个类的其他构造方法 - 必须位于构造方法的第一行
方法详解
1. 方法参数传递:
- 基本类型参数:传递值的副本,方法内修改不影响原始值
- 引用类型参数:传递引用的副本(指向同一对象),方法内可修改对象状态,但不能改变引用本身
2. 方法重载:
- 同一类中,方法名相同但参数列表不同(参数个数、类型或顺序不同)
- 返回类型不作为重载判断条件
3. 可变参数(Varargs):
-
方法参数列表中最后一个参数可以是可变参数,使用
...表示 -
本质是一个数组
1 2 3 4 5public void printNumbers(int... numbers) { for (int num : numbers) { System.out.println(num); } }调用:
printNumbers(1, 2, 3);或printNumbers(new int[]{4, 5, 6});
对象构造过程
- 分配内存空间
- 成员变量默认初始化(基本类型为默认值,引用类型为
null) - 执行实例初始化块(按定义顺序执行)
- 执行构造方法
类之间的关系
1. 依赖(“uses-a"关系):
- 一个类的方法使用另一个类的对象作为参数或局部变量
- 例:
public void processOrder(Customer customer)
2. 聚合(“has-a"关系):
- 一个类包含另一个类的对象作为成员变量
- 例:
private Address address;
3. 继承(“is-a"关系):
- 一个类继承另一个类的属性和方法
- 例:
public class Manager extends Employee
包
-
作用:组织类、避免命名冲突、控制访问权限
-
定义:源文件首行非注释语句
package packageName; -
命名规则:建议使用域名逆序(如
com.example.project) -
访问控制:同包类可互相访问,不同包只能访问
public类 -
导入类:
1 2import packageName.ClassName; // 导入单个类 import packageName.*; // 导入整个包(不包含子包) -
静态导入:导入静态成员
1 2import static java.lang.Math.PI; import static java.util.Arrays.sort;
文档注释
- 使用
/** ... */格式,用于生成API文档 - 主要标签:
@author:作者@version:版本@param:参数说明@return:返回值说明@throws:异常说明
- 通过
javadoc命令生成HTML文档
类设计技巧
- 数据私有:所有字段设为
private,提供公共访问方法 - 对数据初始化:确保所有字段在使用前被初始化
- 避免过多基本类型:考虑用类替代相关基本类型组合
- 慎用访问器/更改器:不必要的字段不提供专门访问方法
- 分解职责过重的类:单一职责原则(SRP)
- 命名清晰:类名名词,方法名动词短语
- 优先使用不可变类:如
String,提高线程安全性
第1-4章复习重点
- Java基础:平台无关性原理、JVM/JRE/JDK区别
- 数据类型:8种基本类型的范围和默认值、引用类型特点
- 流程控制:各种循环和条件语句的使用场景
- 数组:声明、初始化、遍历方法
- 面向对象基础:类与对象关系、封装特性、访问控制
- 构造方法:重载、
this关键字使用、初始化顺序 - 方法:参数传递机制、重载原理、可变参数用法
提示:重点练习类的设计,包括成员变量、构造方法和方法的编写,以及对象的创建与使用
第5章 继承
类、超类和子类
-
继承定义:子类通过
extends关键字继承父类1public class Manager extends Employee { ... } -
子类特性:
- 继承父类非私有成员(字段和方法)
- 可添加新成员
- 可覆盖(override)父类方法
-
构造方法:子类构造方法必须先调用父类构造方法(
super()),且必须位于首行 -
方法覆盖:
1 2@Override // 显式标记覆盖,编译时检查 public double getSalary() { ... } -
强制类型转换:
1 2Manager m = (Manager) employee; // 向下转型需显式转换 if (employee instanceof Manager) { ... } // 使用instanceof检查类型
多态
- 定义:父类引用可以指向子类对象,调用方法时执行实际对象(子类)的方法
- “is-a"原则:子类对象可视为父类对象(如"Manager is an Employee”)
- 动态绑定:运行时根据实际对象类型确定调用的方法
- 编译与运行时:
- 编译时:检查引用类型是否具有该方法
- 运行时:执行实际对象的方法
final关键字
- 修饰类:类不可被继承(如
String类) - 修饰方法:方法不可被覆盖
- 修饰变量:变量变为常量,只能赋值一次
Object:所有类的超类
- 默认继承:所有类(除
Object本身)都直接或间接继承Object - 常用方法:
equals(Object):比较对象是否相等(默认比较引用)hashCode():返回对象哈希码(配合equals使用)toString():返回对象字符串表示(建议重写)getClass():返回对象的Class对象(运行时类型信息)
抽象类
-
定义:包含抽象方法(无实现)的类,必须声明为
abstract1 2 3public abstract class Shape { public abstract double area(); // 抽象方法 } -
特点:
- 不能实例化(不能用
new创建对象) - 子类必须实现所有抽象方法(除非子类也是抽象类)
- 可包含具体方法和字段
- 不能实例化(不能用
第6章 接口与内部类
接口
-
定义:
1 2 3public interface Comparable { int compareTo(Object o); // 接口方法默认public abstract } -
特性:
- 所有方法默认
public abstract - 所有字段默认
public static final - 不能实例化,只能被类实现
- 类通过
implements实现接口 - 一个类可实现多个接口(解决Java单继承限制)
- 所有方法默认
默认方法
-
接口中可提供方法的默认实现,用
default修饰1 2 3public interface Collection { default void forEach(Consumer action) { ... } } -
冲突解决规则:
- 类优先原则:类中方法优先于接口默认方法
- 接口冲突:一个类实现两个接口,且都有相同默认方法,必须在类中重写该方法
lambda表达式
-
定义:简洁表示函数式接口(只有一个抽象方法的接口)的实例
-
基本语法:
1(参数列表) -> { 方法体 } -
简化规则:
- 参数类型可省略(类型推断)
- 单参数时可省略括号
- 方法体只有一条语句可省略花括号和
return
-
示例:
1 2 3 4 5 6 7 8 9// 传统方式 Comparator<String> comp = new Comparator<String>() { public int compare(String s1, String s2) { return s1.length() - s2.length(); } }; // lambda方式 Comparator<String> comp = (s1, s2) -> s1.length() - s2.length();
方法引用
-
定义:直接引用已有方法作为lambda表达式
-
四种形式:
1 2 3 4 5 6 7 8 9 10 11// 对象::实例方法 obj::methodName // 类::静态方法 ClassName::staticMethodName // 类::实例方法(第一个参数作为调用者) ClassName::instanceMethodName // 数组::构造方法 int[]::new
内部类
- 定义:在另一个类内部定义的类
- 类型:
- 成员内部类:在类内但方法外定义,可直接访问外部类所有成员
- 静态内部类:用
static修饰,只能访问外部类静态成员 - 局部内部类:在方法内定义,作用域仅限于该方法
- 匿名内部类:没有名字的内部类,用于创建一次性对象
第7章 异常处理
异常分类
- Throwable:所有错误和异常的根类
- Error:系统内部错误(如
StackOverflowError),应用程序不应捕获 - Exception:程序运行时错误,可分为:
- 运行时异常(RuntimeException):非检查异常(如
NullPointerException) - 检查型异常(Checked Exception):必须显式处理(捕获或声明抛出)
- 运行时异常(RuntimeException):非检查异常(如
- Error:系统内部错误(如
异常处理机制
-
抛出异常:
1 2 3if (value < 0) { throw new IllegalArgumentException("Negative value not allowed"); } -
捕获异常:
1 2 3 4 5 6 7 8 9try { // 可能抛出异常的代码 } catch (ExceptionType1 e) { // 处理ExceptionType1异常 } catch (ExceptionType2 e) { // 处理ExceptionType2异常 } finally { // 无论是否发生异常都执行的代码(如资源清理) } -
多重捕获(Java 7+):
1catch (IOException | SQLException e) { ... } // 捕获多种异常
try-with-resources语句
-
自动关闭资源:适用于实现
AutoCloseable接口的资源(如文件流、数据库连接)1 2 3try (FileInputStream fis = new FileInputStream("file.txt")) { // 使用资源 } // 自动调用fis.close(),即使发生异常 -
多个资源:
1try (ResourceA ra = new ResourceA(); ResourceB rb = new ResourceB()) { ... }
自定义异常
-
继承
Exception(检查型异常)或RuntimeException(非检查型异常) -
建议提供两个构造方法:
1 2 3 4public class MyException extends Exception { public MyException() { super(); } public MyException(String message) { super(message); } }
异常使用最佳实践
-
只在异常情况下使用异常:异常处理比条件判断慢得多
-
异常链:捕获异常后包装成更高层异常,保留原始异常信息
1 2 3try { ... } catch (SQLException e) { throw new ServiceException("Database error", e); // 异常链 } -
不要捕获
Throwable:应捕获具体异常,避免隐藏系统错误 -
优先传递异常:若当前层无法处理,应将异常向上抛出
-
finally慎用return:可能覆盖try块中的return值
第8章 泛型程序设计
为什么使用泛型
-
类型安全:编译时检查类型,避免运行时
ClassCastException -
代码重用:一个类/方法可用于多种类型
-
消除强制类型转换:
1 2 3 4 5 6 7 8 9// 非泛型 List list = new ArrayList(); list.add("Hello"); String s = (String) list.get(0); // 需要强制转换 // 泛型 List<String> list = new ArrayList<>(); list.add("Hello"); String s = list.get(0); // 无需强制转换
定义泛型类
-
语法:
1 2 3 4 5public class Box<T> { private T value; public T getValue() { return value; } public void setValue(T value) { this.value = value; } } -
使用:
1 2Box<Integer> intBox = new Box<>(); intBox.setValue(10);
泛型方法
-
可在普通类中定义泛型方法
1 2 3 4 5public static <T> void printArray(T[] array) { for (T element : array) { System.out.println(element); } } -
调用:
1 2Integer[] intArray = {1, 2, 3}; printArray(intArray); // 自动推断T为Integer
类型变量的限定
-
限制类型变量必须是某个类的子类或实现某个接口
1public <T extends Comparable> void sort(T[] array) { ... } // T必须实现Comparable接口
泛型代码和虚拟机
- 类型擦除:泛型信息只在编译期存在,运行时被擦除
- 泛型类
Box<T>编译后变为原始类Box - 类型变量被替换为上限(若无上限则为
Object)
- 泛型类
- 桥接方法:为保持多态性,编译器生成的特殊方法
- 泛型数组:不能直接创建泛型数组(
new T[]),但可通过强制类型转换实现
泛型的限制与局限性
- 不能实例化类型变量:
new T()不合法 - 不能创建泛型数组:
T[] array = new T[10];不合法 - 静态上下文中类型变量无效:静态方法/字段不能使用类的类型变量
- 不能捕获或抛出泛型类的实例:
catch (T e)不合法 - 不能使用基本类型实例化泛型:需使用包装类(如
Integer代替int)
通配符(Wildcards)
-
上界通配符:
<? extends Type>表示可以接受该类型或其子类型1public void printList(List<? extends Number> list) { ... } // 接受任何Number子类的列表 -
下界通配符:
<? super Type>表示可以接受该类型或其父类型1public void addNumbers(List<? super Integer> list) { ... } // 接受Integer或其父类的列表 -
无界通配符:
<?>等同于<? extends Object>1public void printObjectList(List<?> list) { ... } // 接受任何类型的列表
泛型最佳实践
- 使用泛型集合:如
List<String>而非原始List - 定义泛型方法而非泛型类:若通用性仅限于少数方法
- 合理使用通配符:提高API灵活性
- 必要时使用类型检查和强制转换:在泛型信息丢失时
- 考虑类型安全的容器:如
Collections.checkedList()
第4-8章复习重点
- 面向对象核心:封装、继承、多态的实现与应用场景
- 继承机制:
- 子类与父类关系及构造顺序
- 方法覆盖与
super关键字 final关键字的使用
- 接口与lambda:
- 接口特性与默认方法
- lambda表达式简化函数式接口实现
- 异常处理:
- 检查型与非检查型异常区别
- try-catch-finally与try-with-resources用法
- 自定义异常最佳实践
- 泛型:
- 类型擦除机制
- 通配符使用(上界、下界)
- 泛型类与方法设计
提示:重点练习类的继承关系设计、接口实现、异常处理策略和泛型集合使用,这些是Java开发的核心技能。
第9章 集合
Java集合框架概述
-
集合特点:
- 大小可变,可存储对象引用(基本类型自动装箱)
- 支持泛型,类型安全
- 主要接口:
Collection(单元素集合)和Map(键值对集合)
-
接口与实现分离:
- 面向接口编程,实现类可互换(如
List可用ArrayList或LinkedList) - 提高代码灵活性和可维护性
- 面向接口编程,实现类可互换(如
Collection接口体系
根接口:Collection<E>
- 核心方法:
add(E e)、iterator()、size()、contains(Object o) - 子接口:
List<E>:有序、可重复,支持索引访问- 实现:
ArrayList(动态数组,随机访问快)、LinkedList(双向链表,增删快)
- 实现:
Set<E>:无序、唯一- 实现:
HashSet(哈希表,性能好)、TreeSet(有序,基于红黑树)、LinkedHashSet(插入顺序)
- 实现:
Queue<E>:FIFO(先进先出)- 实现:
LinkedList(也实现Deque)、PriorityQueue(优先级队列)
- 实现:
迭代器
-
功能:遍历集合元素,支持删除操作
-
核心方法:
1 2 3boolean hasNext(); // 是否有下一个元素 E next(); // 返回下一个元素 void remove(); // 删除当前元素(可选操作) -
增强for循环:内部使用迭代器,简化遍历
1for (E element : collection) { ... } -
注意:遍历时直接修改集合结构会抛出
ConcurrentModificationException,应使用迭代器的remove()方法
Map接口
-
特点:存储
key-value对,key唯一 -
核心实现:
HashMap:基于哈希表,性能最佳,无序TreeMap:按键排序(自然顺序或定制比较器)LinkedHashMap:保持插入顺序,可实现LRU缓存Hashtable:线程安全(同步),已过时,推荐使用ConcurrentHashMap
-
视图操作:
1 2 3Set<K> keySet(); // 获取所有key的集合 Collection<V> values(); // 获取所有value的集合 Set<Map.Entry<K, V>> entrySet(); // 获取所有键值对
集合工具类
-
Collections:提供静态方法操作集合- 排序:
sort(List<T> list)(自然顺序)、sort(List<T> list, Comparator<? super T> c)(定制顺序) - 查找:
binarySearch()、max()、min() - 包装:
synchronizedList()(线程安全)、unmodifiableList()(只读) - 填充:
fill(List<T> list, T obj) - 洗牌:
shuffle(List<?> list)
- 排序:
-
Arrays:数组与集合互转1 2 3 4 5// 数组转集合(固定大小,不支持增删) List<String> list = Arrays.asList("a", "b", "c"); // 集合转数组 String[] array = list.toArray(new String[0]);
特殊集合
WeakHashMap:键使用弱引用,当键不再被其他对象强引用时,可被垃圾回收,适用于缓存场景PriorityQueue:优先队列,元素按自然顺序或定制比较器排序,poll()返回最小元素EnumSet:专为枚举类型设计的高效Set实现LinkedHashSet:保持插入顺序的HashSet,遍历时按插入顺序访问
第10章 GUI程序设计
Java GUI工具包简史
-
AWT(Abstract Window Toolkit):
- Java最早的GUI工具包(1995年)
- 依赖操作系统原生组件(重量级组件)
- 组件外观受系统影响,功能有限,现已被Swing和JavaFX替代
-
Swing:
- 完全用Java实现(轻量级组件)
- 跨平台一致外观
- 提供更丰富组件(如表格、树等)
- 包名:
javax.swing,是Java SE标准库一部分
基本GUI构建
1. 窗口(JFrame):
|
|
2. 容器(Container):
- 组件不能独立显示,必须添加到容器中
- 常用容器:
- JFrame:主窗口
- JPanel:轻量级面板,用于组织和嵌套组件
- JScrollPane:带滚动条的容器,用于显示大内容
- JOptionPane:对话框容器,用于显示消息和获取用户输入
布局管理器
- 控制容器中组件的排列方式,Swing提供多种布局:
| 布局管理器 | 特点 | 适用场景 |
|---|---|---|
| FlowLayout | 按添加顺序排列,默认居中对齐 | 简单界面,组件较少 |
| BorderLayout | 分为东、西、南、北、中五个区域 | 主窗口布局,通常中心区域放置主要内容 |
| GridLayout | 网格布局,所有组件大小相同 | 整齐排列的按钮、标签等 |
| GridBagLayout | 灵活网格,可设置组件跨越多个单元格,自定义大小 | 复杂界面,组件大小不一 |
| BoxLayout | 水平或垂直排列,可设置间距 | 工具栏、垂直菜单等 |
-
使用示例:
1 2 3 4 5 6// 设置JFrame使用BorderLayout setLayout(new BorderLayout()); // 向不同区域添加组件 add(new JButton("Top"), BorderLayout.NORTH); add(new JButton("Bottom"), BorderLayout.SOUTH);
事件处理机制
1. 事件模型:
- 事件源:产生事件的组件(如按钮、文本框)
- 事件:描述发生的事情(如点击、输入)
- 事件监听器:接收并处理事件的对象,实现特定监听器接口
2. 常见事件类型:
-
ActionListener:按钮点击、菜单选择等1 2JButton button = new JButton("Click me"); button.addActionListener(e -> System.out.println("Button clicked!")); -
ItemListener:复选框、单选按钮状态变化1 2JCheckBox checkBox = new JCheckBox("Remember me"); checkBox.addItemListener(e -> System.out.println("Checkbox state: " + e.getStateChange())); -
MouseListener:鼠标点击、进入、离开等 -
KeyListener:键盘按键事件
3. 适配器类:
-
为监听器接口提供默认实现,只需重写需要的方法
1 2 3 4 5 6 7// 使用MouseAdapter简化鼠标事件处理 button.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { System.out.println("Mouse clicked at: " + e.getX() + ", " + e.getY()); } });
常用Swing组件
1. 标签(JLabel):显示文本或图像,不响应用户交互
|
|
2. 按钮(JButton):可点击按钮
|
|
3. 文本组件:
- JTextField:单行文本输入
- JPasswordField:密码输入(显示为星号)
- JTextArea:多行文本区域(通常配合JScrollPane使用)
4. 选择组件:
- JCheckBox:复选框,可选中或取消选中
- JRadioButton:单选按钮,需配合ButtonGroup使用(同一组内只能选一个)
- JComboBox:下拉列表,可选择预定义选项
5. 对话框:
-
JOptionPane:简单对话框,用于显示消息、获取用户输入
1 2 3 4 5// 消息对话框 JOptionPane.showMessageDialog(null, "Login successful!"); // 确认对话框 int option = JOptionPane.showConfirmDialog(null, "Do you want to save changes?");
第11章 Swing用户界面组件
Swing高级组件
1. 菜单(Menu):
|
|
2. 工具栏(JToolBar):
|
|
3. 表格(JTable):显示和编辑二维数据
|
|
4. 树(JTree):显示层次结构数据
|
|
布局管理进阶
1. GridBagLayout详解:
-
最灵活的布局管理器,支持组件跨越多个单元格
-
通过
GridBagConstraints设置组件位置、大小、对齐方式等1 2 3 4 5 6 7 8 9 10 11 12 13 14// 设置窗口使用GridBagLayout setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); // 添加组件到(0,0)位置,默认大小 gbc.gridx = 0; gbc.gridy = 0; add(new JLabel("Username:"), gbc); // 添加组件到(1,0)位置,横向填充 gbc.gridx = 1; gbc.gridy = 0; gbc.fill = GridBagConstraints.HORIZONTAL; // 水平方向填充 add(new JTextField(20), gbc);
2. BoxLayout与Box组件:
-
垂直或水平排列组件,自动处理间距
1 2 3 4 5 6// 垂直排列组件 JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.add(new JButton("Button 1")); panel.add(Box.createVerticalStrut(10)); // 添加垂直间距 panel.add(new JButton("Button 2"));
Swing特性与最佳实践
1. 组件边框(Border):
|
|
2. 图标(Icon):
-
使用
ImageIcon加载图片,支持多种格式(如PNG、JPG)1JButton button = new JButton(new ImageIcon("icon.png"));
3. 工具提示(ToolTip):
|
|
4. Swing应用程序结构最佳实践:
-
在事件调度线程(Event Dispatch Thread, EDT)中创建和更新UI
1SwingUtilities.invokeLater(() -> new MyFrame()); -
主窗口设置合适的关闭操作:
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) -
合理使用布局管理器,避免绝对定位
-
使用面板(JPanel)组织相关组件,实现界面模块化
第12章 并发
线程基础
1. 线程与进程:
- 进程:独立执行的程序,拥有自己的内存空间
- 线程:进程内的执行单元,共享进程内存,提高程序并发性
2. 创建线程的方式:
|
|
3. 线程状态(6种):
|
|
| 状态 | 描述 |
|---|---|
| NEW | 线程已创建但未启动(调用start()前) |
| RUNNABLE | 线程可运行(正在执行或等待CPU时间片) |
| BLOCKED | 线程阻塞等待监视器锁(synchronized) |
| WAITING | 线程无限等待(如调用Object.wait()) |
| TIMED_WAITING | 线程等待指定时间(如Thread.sleep()) |
| TERMINATED | 线程执行完毕或异常终止 |
线程属性与控制
1. 线程优先级:
|
|
- 优先级只是建议,不保证执行顺序,不同操作系统实现不同
2. 线程名称:
|
|
3. 守护线程(Daemon Thread):
|
|
- 为其他线程服务的线程(如垃圾回收线程)
- 当所有非守护线程结束时,JVM会自动终止守护线程
4. 线程中断:
|
|
- 协作式中断:线程需自行检查中断状态并处理
- 不推荐使用
stop()、suspend()、resume()等已废弃方法
同步机制
1. 竞态条件(Race Condition):
- 多个线程同时访问共享资源且执行顺序不确定,导致结果不可预测
- 例:多个线程同时修改同一个计数器,可能导致计数丢失
2. synchronized关键字:
|
|
- 保证同一时间只有一个线程执行同步代码
- 可重入:同一线程可多次获取同一把锁
3. 锁对象(Lock)(Java 5+):
|
|
ReentrantLock:可重入锁,功能类似synchronized,但更灵活ReentrantReadWriteLock:读写锁,允许多个读线程同时访问,写线程独占
4. 条件对象(Condition):
|
|
- 配合锁使用,实现更精细的线程间通信
5. volatile关键字:
|
|
- 确保变量在多个线程间的可见性(一个线程修改后,其他线程立即可见)
- 不保证原子性,适用于状态标记等简单场景,不适用于复合操作
线程安全集合
- **并发包(Java.util.concurrent)**提供线程安全的集合:
| 集合类 | 特点 | 适用场景 |
|---|---|---|
ConcurrentHashMap |
高效线程安全哈希表,分段锁机制 | 高并发读写,替代Hashtable |
CopyOnWriteArrayList |
写时复制,适合读多写少场景 | 事件监听、日志记录等 |
ConcurrentLinkedQueue |
线程安全的链式队列,无锁实现 | 多线程间安全传递数据 |
BlockingQueue |
阻塞队列,提供put()和take()等阻塞方法 | 生产者-消费者模型 |
ConcurrentSkipListMap |
线程安全的有序Map,基于跳表实现 | 高并发下的有序数据访问 |
-
使用示例:
1 2 3 4// 使用ConcurrentHashMap Map<String, Integer> map = new ConcurrentHashMap<>(); map.put("key", 1); int value = map.get("key");
任务与线程池
1. 执行器框架(Executor Framework):
|
|
2. 线程池类型:
newFixedThreadPool(int nThreads):固定大小线程池,重用固定数量线程newCachedThreadPool():缓存线程池,按需创建线程,空闲线程会被回收newSingleThreadExecutor():单线程执行器,保证任务按顺序执行newScheduledThreadPool(int corePoolSize):定时线程池,支持任务定时或周期性执行
3. 控制任务组:
|
|
异步计算
1. Future与Callable:
|
|
2. CompletableFuture(Java 8+):
-
支持异步操作的链式调用和组合,无需显式线程管理
1 2 3CompletableFuture.supplyAsync(() -> "Hello") // 异步执行任务 .thenApply(s -> s + " World") // 处理结果 .thenAccept(System.out::println); // 消费最终结果(无返回)
3. 异步计算最佳实践:
- 避免在UI线程执行耗时操作,使用线程池或CompletableFuture
- 使用
CompletableFuture处理多个异步任务的组合 - 对长时间运行任务提供取消机制
- 正确处理异常(使用
exceptionally()或handle())
第9-12章复习重点
-
集合框架:
- Collection与Map接口体系结构
- 常用实现类特点与适用场景(如ArrayList vs LinkedList,HashMap vs TreeMap)
- 迭代器使用与注意事项
- Collections工具类方法
-
GUI编程:
- Swing组件层次结构(容器与组件关系)
- 布局管理器(FlowLayout、BorderLayout、GridBagLayout)使用
- 事件处理机制(监听器、适配器)
- 常用组件(JButton、JLabel、JTextField等)使用
-
并发编程:
- 线程创建方式(Thread、Runnable、Callable)
- 线程同步机制(synchronized、Lock、Condition、volatile)
- 线程池使用(Executor框架)
- 线程安全集合与异步计算(Future、CompletableFuture)
提示:重点练习集合的实际应用、GUI布局设计和并发程序调试,这些是Java开发的核心技能,也是面试高频考点。