202502150141邓俊杰
一、Java语言基础篇
1.1 Java语言概述
参考了博主爱的叹息该篇文章
Java发展史及版本详细说明_java版本-CSDN博客
https://blog.csdn.net/zp357252539/article/details/147495182
1. Java 1.0 (1996年1月23日)
核心功能:
首个正式版本,支持面向对象编程、垃圾回收、网络编程。
包含基础类库(java.lang、java.io、java.awt)。
支持Applet(浏览器嵌入的小程序)。
关键特性:
跨平台(Write Once, Run Anywhere)。
基础集合类(Vector、Hashtable)。
AWT(Abstract Window Toolkit,用于GUI开发)。
2. Java 1.1 (1997年2月19日)
核心功能:
引入内部类(Inner Classes)。
增强GUI支持(Swing框架的前身)。
关键特性:
Reflection(反射机制)。
RMI(Remote Method Invocation,远程方法调用)。
JDBC(数据库连接)的早期版本。
3. Java 1.2 (Java 2, 1998年12月8日)
核心功能:
正式更名为Java 2,分为三个平台:J2SE(标准版)、J2EE(企业版)、J2ME(微型版)。
引入集合框架(java.util.Collections)。
关键特性:
Swing GUI框架(替代AWT)。
校验编译器(javac改进)。
严格的异常处理(必须声明或捕获检查型异常)。
4. Java 1.3 (2000年5月8日)
核心功能:
增强JIT编译器性能。
引入日志框架(java.util.logging)。
关键特性:
HotSpot JVM(Oracle的高性能JVM)。
音频API(javax.sound)。
5. Java 1.4 (2002年2月6日)
核心功能:
正则表达式(java.util.regex)。
遍历器模式(Iterator)。
关键特性:
Assertion(断言,assert关键字)。
集成Apache的XML解析库(javax.xml)。
6. Java 5 (Java 5.0, 2004年9月30日)
核心功能:
重大升级,引入多项语法和功能革新。
关键特性:
泛型(Generics)。
枚举(Enums)。
注解(Annotations,如@Override)。
自动装箱/拆箱(Autoboxing/Unboxing)。
增强for循环(for-each)。
可变参数(Varargs)。
Concurrent包(java.util.concurrent,多线程优化)。
7. Java 6 (2006年12月11日)
核心功能:
改进性能和兼容性。
关键特性:
Scripting API(支持JavaScript等脚本语言)。
Pluggable Annotation(自定义注解处理器)。
JDBC 4.0(支持类型安全查询)。
Drag-and-Drop API。
8. Java 7 (2011年7月28日)
核心功能:
语法和API的进一步简化。
关键特性:
Try-with-resources(自动资源管理)。
钻石操作符(<>推断泛型类型)。
NIO 2.0(增强文件系统API,java.nio.file)。
Switch支持字符串(预览功能)。
Fork/Join框架(并行任务处理)。
9. Java 8 (2014年3月18日)
核心功能:
函数式编程支持,引发Java生态巨大变革。
关键特性:
Lambda表达式(->语法)。
Stream API(集合数据处理)。
默认方法(接口中的默认实现)。
新的日期时间API(java.time包)。
Optional类(避免空指针异常)。
重复注解(@Repeatable)。
10. Java 9 (2017年9月21日)
核心功能:
模块化系统(JPMS),Java首次引入模块化。
关键特性:
Jigsaw项目(模块化JDK,module-info.java)。
JShell(交互式命令行工具)。
HTTP客户端(java.net.http)。
私有接口方法(接口内部可见方法)。
集合工厂方法(List.of()等不可变集合)。
11. Java 10 (2018年3月20日)
核心功能:
短期发布周期(每6个月一次)的首个版本。
关键特性:
局部变量类型推断(var关键字)。
垃圾回收器改进(G1成为默认GC)。
并行Full GC(ZGC的预览)。
12. Java 11 (2018年9月25日,LTS)
核心功能:
长期支持(LTS)版本,企业级首选。
关键特性:
Epsilon垃圾收集器(无操作GC,用于测试)。
HTTP客户端正式版(Java 9的预览功能升级)。
Unicode 8.0支持。
Deprecate Nashorn引擎(JavaScript引擎)。
13. Java 14 (2020年3月17日)
核心功能:
预览特性的快速迭代。
关键特性:
Records(数据类,预览)。
Switch表达式(表达式式switch,预览)。
Pattern Matching for instanceof(预览)。
文本块(多行字符串,"""语法)。
14. Java 15 (2020年9月15日)
核心功能:
增强预览特性。
关键特性:
Records正式版。
文本块正式版。
隐藏类(jdk.internal.vm.hidden)。
密封类(sealed,预览)。
15. Java 16 (2021年3月16日)
核心功能:
新特性正式化。
关键特性:
密封类正式版。
弃用remove()方法(集合的remove()改为removeIf())。
Vector API(Incubator)(SIMD指令支持)。
模式匹配增强(instanceof与类型匹配结合)。
16. Java 17 (2021年9月14日,LTS)
核心功能:
LTS版本,企业长期支持。
关键特性:
Sealed Classes正式版。
Switch表达式正式版。
移除Java EE模块(如java.xml.bind)。
强封装JDK内部API(--add-opens)。
Pattern Matching for instanceof正式版。
17. Java 18 (2022年3月15日)
核心功能:
改进性能和可维护性。
关键特性:
虚拟线程(Virtual Threads)(预览,轻量级线程)。
结构化并发框架(StructuredConcurrent API)。
模式匹配switch(switch支持类型匹配)。
18. Java 19 (2022年9月19日)
核心功能:
语言和API优化。
关键特性:
虚拟线程(Virtual Threads)第二版(改进调度)。
结构化并发增强(StructuredConcurrent改进)。
记录模式(Record Patterns)(解构record数据)。
19. Java 20 (2023年3月21日)
核心功能:
性能和工具改进。
关键特性:
虚拟线程(Virtual Threads)正式版。
强封装JDK内部API增强(--illegal-access)。
模式匹配switch正式版。
Vector API第二版(SIMD优化)。
20.Java 21 (2023年9月19日)
核心功能:
语言与API创新:虚拟线程正式版(JEP 444)
字符串模板预览(JEP 430)、模式匹配switch(JEP 441)
记录模式(JEP 440)
性能与工具:分代ZGC(JEP 439)、结构化并发预览(JEP 453)、外部函数与内部
API预览(JEP 442)
21.Java22 (2024年3月19日)
核心功能:
语言与API打磨:外部函数与内部API正式版(JEP 454)、未命名模式和变量正式版(JEP 456)
Stream Gatherers预览(JEP 461)。
性能与工具:G1区域固定(JEP 423)、启动多文件源码程序(JEP 458)。
22.Java23 (2024年9月17日)
核心功能:模块导入声明预览、模式/instanceof/switch支持基本数据类型预览、灵活的构造函数体第二预览(JEP 447)。库与工具:类文件API第二预览(JEP 457)、结构并发第三预览(JEP 453)、支持Markdown编写文档注释。
性能:分代ZGC成为默认。
本博客目前最新的为Java24,目前还在完善中,这里不列举出来了。
1.2 Java三大平台体系
核心概念及知识点:
Java SE (Standard Edition):Java标准版,包含Java语言的核心类库,用于开发桌面应用程序
Java EE (Enterprise Edition):Java企业版,用于开发企业级Web应用,包含Servlet、JSP、EJB等
Java ME (Micro Edition):Java微型版,用于开发移动设备和嵌入式系统应用(很少使用)
平台对比:
| 平台 | 目标设备 | 主要用途 | 核心技术 |
| Java SE | 桌面电脑 | 桌面应用开发 | AWT、Swing、集合框架、多线程 |
| Java EE | 服务器 | 企业级Web应用 | Servlet、JSP、JDBC、Web服务 |
| Java ME | 移动设备 | 嵌入式应用 | CLDC、MIDP、移动API |
个人理解:Java三大平台体现了Java语言的广泛适用性,从桌面到企业到移动设备都有对应的解决方案。这种分层架构让开发者可以根据具体需求选择合适的平台,提高了开发效率。
学习心得:理解平台差异有助于在实际开发中做出正确的架构选择。比如开发网站应用时选择Java EE,开发桌面工具时选择Java SE。
1.3 Java"跨平台"原理
核心概念及知识点:
JVM (Java Virtual Machine):Java虚拟机,负责执行Java字节码。
字节码 (Bytecode):.class文件,Java源代码编译后的中间代码。
JRE (Java Runtime Environment):Java运行时环境,包含JVM和核心类库。
JDK (Java Development Kit):Java开发工具包,包含JRE和开发工具
跨平台执行流程:
-
编写源代码:.java文件
-
编译:javac编译器将.java文件编译为.class字节码文件
-
运行:JVM解释执行字节码文件
关键特性:
一次编译,到处运行:Write once, run anywhere
JVM适配不同操作系统:Windows JVM、Linux JVM、macOS JVM等
java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}
编译命令:`javac HelloWorld.java`
运行命令:`java HelloWorld`
个人理解:Java的跨平台性是其最大的优势之一。通过JVM抽象了底层操作系统的差异,开发者只需要关注业务逻辑而不用关心平台细节。
学习心得:刚开始学习时,对JVM的概念比较模糊。通过实践编译和运行Java程序,才真正理解了"一次编译,到处运行"的含义。
遇到的难点:环境变量配置。刚开始配置JAVA_HOME、PATH等环境变量时经常出错。
克服方法:
免费版本:
(1)仔细阅读官方文档,按照步骤一步步配置,配置完成后通过`java -version`和`javac -version`验证配置是否正确。
(2)对AI进行拷打,把所有报错信息、想问的问题全部问AI,AI会给出对应的解决方案,将方案贯彻落实即可。
(3)加广大Java群,问问有没有好心人愿意帮忙,量变引起质变。(女生可能比较多人愿意帮忙)
(4)找老师,最好让老师直接过来帮忙解决。
付费版本:
(1)在CSDN下面评论,有偿找人帮忙。
(2)去XianYu找人。
二、Java基础语法
2.1 变量和数据类型
核心概念及知识点:
八种基本数据类型:
整数类型:byte(8位)、short(16位)、int(32位)、long(64位)
浮点类型:float(32位)、double(64位)
字符类型:char(16位Unicode)
布尔类型:boolean
引用数据类型:类、接口、数组等
变量声明和初始化
类型转换:自动类型转换、强制类型转换
示例代码:
java
public class DataTypesDemo {
public static void main(String[] args) {
// 基本数据类型
byte b = 127;
short s = 32767;
int i = 2147483647;
long l = 9223372036854775807L;
float f = 3.14f;
double d = 3.141592653589793;
char c = 'A';
boolean bool = true;
// 引用数据类型
String str = "Hello Java";
// 类型转换
int intValue = 100;
double doubleValue = intValue; // 自动类型转换
double pi = 3.14159;
int intPi = (int) pi; // 强制类型转换
System.out.println("intPi = " + intPi); // 输出:3
}
}
个人理解:Java的数据类型设计体现了内存使用效率和编程便利性的平衡。基本数据类型提供了对内存的精确控制,而引用类型则提供了面向对象的编程能力。
学习心得:掌握了不同数据类型的取值范围和内存占用对于编写高效代码很重要。
遇到的难点:浮点数精度问题,0.1 + 0.2 ≠ 0.3的情况经常导致困惑。
克服方法:了解IEEE 754浮点数标准,使用BigDecimal处理精确计算。
2.2 运算符
核心概念及知识点:
算术运算符:+、-、*、/、%、++、--
关系运算符:<、>、<=、>=、==、!=
逻辑运算符:&&、||、!
位运算符:&、|、^、~、<<、>>、>>>
-赋值运算符:=、+=、-=、*=、/=等
三元运算符:? :
示例代码:
java
public class OperatorsDemo {
public static void main(String[] args) {
int a = 10, b = 20;
// 算术运算符
System.out.println("a + b = " + (a + b)); // 30
System.out.println("a % b = " + (a % b)); // 10
// 关系运算符
System.out.println("a > b = " + (a > b)); // false
// 逻辑运算符
boolean x = true, y = false;
System.out.println("x && y = " + (x && y)); // false
System.out.println("x || y = " + (x || y)); // true
// 三元运算符
int max = (a > b) ? a : b;
System.out.println("max = " + max); // 20
}
}
个人理解:运算符是编程的基础,熟练掌握各种运算符的使用可以让代码更加简洁高效。
学习心得:位运算符在某些场景下可以显著提高性能,比如权限控制、状态压缩等。
2.3 控制流程语句
核心概念及知识点:
条件语句:if-else、switch
循环语句:for、while、do-while
跳转语句:break、continue、return
示例代码:
java
public class ControlFlowDemo {
public static void main(String[] args) {
// if-else语句
int score = 85;
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 70) {
System.out.println("中等");
} else {
System.out.println("不及格");
}
// switch语句
int day = 3;
switch (day) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
default:
System.out.println("其他");
}
// for循环
for (int i = 1; i <= 5; i++) {
System.out.println("第" + i + "次循环");
}
// while循环
int count = 1;
while (count <= 3) {
System.out.println("while循环:" + count);
count++;
}
// do-while循环
int num = 1;
do {
System.out.println("do-while循环:" + num);
num++;
} while (num <= 3);
}
}
个人理解:控制流程语句是实现程序逻辑的基础,合理使用可以让程序更加灵活和可读。
学习心得:在实际开发中,for-each循环和增强for循环使用频率很高,简化了集合遍历的代码。
遇到的难点:循环嵌套时逻辑容易混乱。
克服方法:使用调试器单步执行,或者在纸上画流程图理清逻辑关系。
三、面向对象编程
3.1 类和对象
核心概念及知识点:
类 (Class):对象的模板,定义对象的属性和方法
对象 (Object):类的实例,通过new关键字创建
属性 (Fields):类的成员变量
方法 (Methods):类的成员函数
构造方法 (Constructor):对象初始化时调用的特殊方法
示例代码:
java
// 定义一个学生类
public class Student {
// 属性
private String name;
private int age;
private String studentId;
// 构造方法
public Student(String name, int age, String studentId) {
this.name = name;
this.age = age;
this.studentId = studentId;
}
// 默认构造方法
public Student() {
}
// 方法
public void study() {
System.out.println(name + "正在学习");
}
public void introduce() {
System.out.println("我叫" + name + ",年龄" + age + ",学号" + studentId);
}
// getter和setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
java
// 测试类
public class TestStudent {
public static void main(String[] args) {
// 创建对象
Student student1 = new Student("张三", 20, "2023001");
Student student2 = new Student();
student2.setName("李四");
student1.introduce();
student1.study();
student2.introduce();
}
}
个人理解:面向对象编程是Java的核心思想,通过类和对象可以更好地组织和管理代码,提高代码的可重用性和可维护性。
学习心得:封装是面向对象的核心概念,通过private修饰符隐藏实现细节,只暴露必要的接口。
遇到的难点:刚开始区分类和对象的关系比较困难。
克服方法:类是蓝图,对象是根据蓝图建造的房子。这个比喻帮助我理解了两者的关系。
3.2 三大特征
3.2.1 封装 (Encapsulation)
核心概念:将数据和行为包装在一起,对外部隐藏实现细节,只提供公共接口访问。
java
public class BankAccount {
private double balance; // 私有属性,外部无法直接访问
public BankAccount(double initialBalance) {
this.balance = initialBalance;
}
// 公共方法访问私有属性
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("存款成功,余额:" + balance);
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("取款成功,余额:" + balance);
} else {
System.out.println("余额不足");
}
}
public double getBalance() {
return balance;
}
}
个人理解:封装保护了数据的完整性,防止外部随意修改对象的内部状态。
3.2.2 继承 (Inheritance)
核心概念:子类继承父类的属性和方法,实现代码复用。使用extends关键字。
java
// 父类
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + "正在吃东西");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
}
// 子类继承父类
public class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类构造方法
}
// 重写父类方法
@Override
public void eat() {
System.out.println(name + "正在吃狗粮");
}
// 子类特有的方法
public void bark() {
System.out.println(name + "汪汪叫");
}
}
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void eat() {
System.out.println(name + "正在吃鱼");
}
public void meow() {
System.out.println(name + "喵喵叫");
}
}
个人理解:继承建立了类之间的"is-a"关系,促进了代码的层次化和复用。
遇到的难点:方法重写和方法重载的区别容易混淆。
克服方法:重写是子类覆盖父类方法,重载是同一个类中方法名相同但参数不同的情况。
3.2.3 多态 (Polymorphism)
核心概念:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
实现方式:
(1)编译时多态:方法重载
(2)运行时多态:方法重写 + 向上转型
java
public class PolymorphismDemo {
public static void main(String[] args) {
Animal dog = new Dog("旺财"); // 向上转型
Animal cat = new Cat("小花");
// 运行时多态:调用重写的方法
dog.eat(); // 输出:旺财正在吃狗粮
cat.eat(); // 输出:小花正在吃鱼
// 向下转型访问子类特有方法
if (dog instanceof Dog) {
((Dog) dog).bark(); // 输出:旺财汪汪叫
}
}
}
个人理解:多态提高了代码的灵活性和扩展性,体现了面向对象编程的精髓。
学习心得:理解多态的关键在于掌握向上转型和向下转型,以及instanceof关键字的使用。
四、Java数组
核心概念及知识点:
数组定义和初始化
数组遍历:普通for循环、增强for循环
多维数组
Arrays工具类
java
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
// 一维数组的声明和初始化
int[] arr1 = new int[5]; // 声明并分配空间
int[] arr2 = {1, 2, 3, 4, 5}; // 声明并初始化
int[] arr3 = new int[]{1, 2, 3, 4, 5}; // 另一种初始化方式
// 数组赋值
arr1[0] = 10;
arr1[1] = 20;
// 数组遍历
System.out.println("普通for循环遍历:");
for (int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i] + " ");
}
System.out.println();
System.out.println("增强for循环遍历:");
for (int num : arr2) {
System.out.print(num + " ");
}
System.out.println();
// 多维数组
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
System.out.println("二维数组遍历:");
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
// Arrays工具类使用
Arrays.sort(arr2); // 排序
System.out.println("排序后:" + Arrays.toString(arr2));
int index = Arrays.binarySearch(arr2, 3); // 二分查找
System.out.println("元素3的位置:" + index);
}
}
个人理解:数组是Java中最基本的数据结构之一,虽然集合框架提供了更灵活的数据结构,但在某些场景下数组仍然是最佳选择。
学习心得:掌握Arrays工具类的常用方法可以大大提高开发效率。
遇到的难点:多维数组的初始化和遍历语法容易出错。
克服方法:多练习不同维度的数组操作,从简单的一维数组开始逐步过渡到复杂的多维数组。
五、异常处理
异常分类:
Checked Exception:受检异常,必须处理
Runtime Exception:运行时异常,不需要强制处理
Error:错误,通常是系统级错误
异常处理机制:try-catch-finally、throw、throws
自定义异常:
java
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class ExceptionDemo {
public static void main(String[] args) {
// try-catch-finally
FileReader reader = null;
try {
reader = new FileReader("test.txt");
// 读取文件内容
int data = reader.read();
System.out.println("读取到的字符:" + (char) data);
} catch (IOException e) {
System.out.println("文件读取错误:" + e.getMessage());
} finally {
// 无论是否发生异常都会执行
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
System.out.println("关闭文件流失败:" + e.getMessage());
}
}
}
// throw和throws
try {
checkAge(-5);
} catch (IllegalArgumentException e) {
System.out.println("捕获异常:" + e.getMessage());
}
}
// 方法声明抛出异常
public static void checkAge(int age) throws IllegalArgumentException {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
System.out.println("年龄:" + age);
}
}
// 自定义异常
class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
class CustomExceptionDemo {
public static void main(String[] args) {
try {
validateScore(150);
} catch (CustomException e) {
System.out.println("自定义异常:" + e.getMessage());
}
}
public static void validateScore(int score) throws CustomException {
if (score < 0 || score > 100) {
throw new CustomException("分数必须在0-100之间");
}
System.out.println("分数:" + score);
}
}
个人理解:异常处理是程序健壮性的重要保障,能有效防止程序因意外情况而崩溃。
学习心得:合理使用异常可以让代码更加清晰,错误处理逻辑和正常业务逻辑分离。
遇到的难点:何时使用受检异常何时使用运行时异常的判断。
克服方法:受检异常用于可预期的、需要调用者处理的异常;运行时异常用于编程错误或不可预期的异常。
六、Java集合框架
6.1 集合框架概述
核心概念及知识点:
Collection接口:单列集合的根接口
Map接口:双列集合的根接口
集合框架层次结构
泛型在集合中的应用
6.2 List接口及实现类
ArrayList、LinkedList、Vector
java
import java.util.*;
public class ListDemo {
public static void main(String[] args) {
// ArrayList
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");
arrayList.add("C++");
System.out.println("ArrayList:" + arrayList);
System.out.println("第一个元素:" + arrayList.get(0));
// LinkedList
List<String> linkedList = new LinkedList<>();
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.addFirst("Orange"); // LinkedList特有方法
linkedList.addLast("Grape");
System.out.println("LinkedList:" + linkedList);
// Vector(线程安全)
Vector<String> vector = new Vector<>();
vector.add("Thread1");
vector.add("Thread2");
System.out.println("Vector:" + vector);
}
}
个人理解:List是最常用的集合类型之一,根据不同的需求选择合适的实现类:ArrayList适用于随机访问,LinkedList适用于频繁插入删除。
6.3 Set接口及实现类
HashSet、TreeSet、LinkedHashSet
java
import java.util.*;
public class SetDemo {
public static void main(String[] args) {
// HashSet - 无序,不重复
Set<String> hashSet = new HashSet<>();
hashSet.add("Java");
hashSet.add("Python");
hashSet.add("Java"); // 重复元素不会添加
System.out.println("HashSet:" + hashSet);
// TreeSet - 有序,不重复
Set<String> treeSet = new TreeSet<>();
treeSet.add("C++");
treeSet.add("Java");
treeSet.add("Python");
System.out.println("TreeSet(有序):" + treeSet);
// LinkedHashSet - 保持插入顺序
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("First");
linkedHashSet.add("Second");
linkedHashSet.add("Third");
System.out.println("LinkedHashSet:" + linkedHashSet);
}
}
个人理解:Set保证了元素的唯一性,在需要去重和快速查找的场景下非常有用。
6.4 Map接口及实现类
HashMap、TreeMap、LinkedHashMap
java
import java.util.*;
public class MapDemo {
public static void main(String[] args) {
// HashMap
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Java", 90);
hashMap.put("Python", 85);
hashMap.put("C++", 80);
System.out.println("HashMap:" + hashMap);
System.out.println("Java的分数:" + hashMap.get("Java"));
// 遍历Map
System.out.println("遍历HashMap:");
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
// TreeMap - 有序
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("C++", 80);
treeMap.put("Java", 90);
treeMap.put("Python", 85);
System.out.println("TreeMap(按键排序):" + treeMap);
}
}
七、多线程编程
7.1 线程基础
核心概念及知识点:
进程与线程:进程是资源分配的基本单位,线程是CPU调度的基本单位
线程的创建方式:
继承Thread类
实现Runnable接口
实现Callable接口
线程生命周期:新建、就绪、运行、阻塞、死亡
方式1:继承Thread类
java
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Thread运行:" + i);
try {
Thread.sleep(1000); // 休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
方式2:实现Runnable接口
java
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Runnable运行:" + i);
}
}
}
方式3:实现Callable接口(有返回值)
java
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
public class ThreadDemo {
public static void main(String[] args) {
// 启动线程方式1
MyThread thread1 = new MyThread();
thread1.start(); // 不要调用run()方法
// 启动线程方式2
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
// 启动线程方式3
FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
Thread thread3 = new Thread(futureTask);
thread3.start();
try {
Integer result = futureTask.get(); // 获取返回值
System.out.println("Callable计算结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
个人理解:多线程是JavaSE的重要特性,可以提高程序的并发性能和响应性。
学习心得:线程创建的三种方式各有优缺点,实现Runnable接口更加灵活,支持多继承。
7.2 线程同步
核心概念及知识点:
线程安全问题:多个线程同时访问共享资源时可能出现数据不一致
同步机制:
synchronized关键字
Lock接口
死锁:两个或多个线程相互等待对方释放资源
java
// 线程不安全示例
class Counter {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
// 线程安全示例 - synchronized
class SafeCounter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
// Lock接口示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class LockCounter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // 确保锁被释放
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
public class SynchronizationDemo {
public static void main(String[] args) {
SafeCounter counter = new SafeCounter();
// 创建多个线程同时操作
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最终计数:" + counter.getCount()); // 应该输出2000
}
}
个人理解:线程同步是多线程编程的核心,确保了数据的正确性和一致性。
学习心得:synchronized和Lock各有优势,synchronized使用简单,Lock更加灵活。
遇到的难点:死锁的产生和避免。刚开始编写多线程程序时经常遇到死锁问题。
克服方法:遵循"按固定顺序获取锁"的原则,避免嵌套锁的使用,及时释放锁资源。
7.3 线程通信
核心概念及知识点:
wait()、notify()、notifyAll()
生产者消费者模式
BlockingQueue
java
import java.util.LinkedList;
import java.util.Queue;
// 生产者消费者模式 - wait/notify
class Buffer {
private Queue<Integer> queue = new LinkedList<>();
private final int CAPACITY = 5;
public synchronized void produce(int item) throws InterruptedException {
while (queue.size() == CAPACITY) {
wait(); // 队列满,等待消费者消费
}
queue.add(item);
System.out.println("生产了:" + item);
notifyAll(); // 通知等待的消费者
}
public synchronized int consume() throws InterruptedException {
while (queue.isEmpty()) {
wait(); // 队列空,等待生产者生产
}
int item = queue.poll();
System.out.println("消费了:" + item);
notifyAll(); // 通知等待的生产者
return item;
}
}
class Producer extends Thread {
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
buffer.produce(i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
buffer.consume();
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ProducerConsumerDemo {
public static void main(String[] args) {
Buffer buffer = new Buffer();
Producer producer = new Producer(buffer);
Consumer consumer = new Consumer(buffer);
producer.start();
consumer.start();
}
}
个人理解:线程通信是多线程协作的基础,通过wait/notify机制可以实现线程间的协调工作。
学习心得:生产者消费者模式是经典的多线程设计模式,理解这个模式对掌握多线程编程很重要。
八、常用工具类
8.1 String类
核心概念及知识点:
String的不可变性
字符串常量池
StringBuilder和StringBuffer的区别
java
public class StringDemo {
public static void main(String[] args) {
// String基本操作
String str1 = "Hello";
String str2 = "Java";
String str3 = str1 + " " + str2; // 字符串拼接
System.out.println(str3); // Hello Java
// 字符串比较
String s1 = "Java";
String s2 = new String("Java");
System.out.println(s1 == s2); // false,比较引用
System.out.println(s1.equals(s2)); // true,比较内容
// 字符串常量池
String s3 = "Java";
System.out.println(s1 == s3); // true,指向常量池中的同一对象
// StringBuilder - 非线程安全,高效率
StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" ").append("World");
System.out.println(sb.toString());
// StringBuffer - 线程安全,效率较低
StringBuffer sbuf = new StringBuffer();
sbuf.append("Thread").append(" ").append("Safe");
System.out.println(sbuf.toString());
// 常用方法
String text = "Hello, Java World!";
System.out.println("长度:" + text.length());
System.out.println("子串:" + text.substring(7, 11)); // Java
System.out.println("大写:" + text.toUpperCase());
System.out.println("包含Java:" + text.contains("Java"));
System.out.println("替换:" + text.replace("World", "Universe"));
}
}
8.2 日期时间处理
java
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class DateTimeDemo {
public static void main(String[] args) {
// 旧的日期API(不推荐使用)
Date date = new Date();
System.out.println("当前日期(旧API):" + date);
// 新的日期时间API (Java 8+)
LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("当前日期:" + today);
System.out.println("当前时间:" + now);
System.out.println("当前日期时间:" + currentDateTime);
// 日期格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = currentDateTime.format(formatter);
System.out.println("格式化后:" + formattedDateTime);
// 日期解析
String dateStr = "2024-01-01 12:30:45";
LocalDateTime parsedDateTime = LocalDateTime.parse(dateStr, formatter);
System.out.println("解析后:" + parsedDateTime);
// 日期计算
LocalDate tomorrow = today.plusDays(1);
LocalDate lastWeek = today.minusWeeks(1);
System.out.println("明天:" + tomorrow);
System.out.println("上周今天:" + lastWeek);
// 计算两个日期之间的差异
LocalDate birthDate = LocalDate.of(2000, 1, 1);
Period period = Period.between(birthDate, today);
System.out.println("年龄:" + period.getYears() + "岁" + period.getMonths() + "个月");
}
}
个人理解:Java 8引入的新日期时间API比旧的Date类更加直观和易用,强烈推荐在新的项目中使用。
学习心得:掌握日期时间的格式化和解析是实际开发中的常见需求。
遇到的难点:时区处理。不同地区的时间表示方式容易出错。
克服方法:使用ZonedDateTime类处理时区相关的操作,明确指定时区避免歧义。
个人理解:泛型让代码更加类型安全,减少了运行时类型转换错误,提高了代码的可读性和重用性。
九、泛型
核心概念及知识点:
泛型类和泛型方法**
类型参数的限定
通配符:?、? extends T、? super T
泛型擦除
java
import java.util.*;
// 泛型类
public class GenericBox<T> {
private T content;
public GenericBox(T content) {
this.content = content;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
}
// 泛型方法
class GenericMethod {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
// 限定类型参数
public static <T extends Number> double sum(T[] numbers) {
double total = 0.0;
for (T num : numbers) {
total += num.doubleValue();
}
return total;
}
}
// 通配符示例
class WildcardDemo {
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}
// 上界通配符
public static double sumOfList(List<? extends Number> list) {
double sum = 0.0;
for (Number num : list) {
sum += num.doubleValue();
}
return sum;
}
// 下界通配符
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
}
public class GenericsDemo {
public static void main(String[] args) {
// 泛型类使用
GenericBox<String> stringBox = new GenericBox<>("Hello Generics");
GenericBox<Integer> intBox = new GenericBox<>(123);
System.out.println("String Box: " + stringBox.getContent());
System.out.println("Integer Box: " + intBox.getContent());
// 泛型方法使用
Integer[] intArray = {1, 2, 3, 4, 5};
String[] strArray = {"Java", "Python", "C++"};
GenericMethod.printArray(intArray);
GenericMethod.printArray(strArray);
Double[] doubleArray = {1.1, 2.2, 3.3};
System.out.println("Sum: " + GenericMethod.sum(doubleArray));
// 通配符使用
List<Integer> intList = Arrays.asList(1, 2, 3);
List<String> strList = Arrays.asList("A", "B", "C");
WildcardDemo.printList(intList);
WildcardDemo.printList(strList);
List<Double> doubleList = Arrays.asList(1.0, 2.0, 3.0);
System.out.println("Sum of doubles: " + WildcardDemo.sumOfList(doubleList));
List<Number> numList = new ArrayList<>();
WildcardDemo.addNumbers(numList);
System.out.println("Numbers added: " + numList);
}
}
个人理解:泛型让代码更加类型安全,减少了运行时类型转换错误,提高了代码的可读性和重用性。
学习心得:泛型的学习曲线比较陡峭,但一旦掌握就能显著提升代码质量。
遇到的难点:通配符的使用规则。? extends T 和 ? super T 的区别和应用场景容易混淆。
克服方法:记住PECS原则(Producer Extends, Consumer Super),生产者使用extends,消费者使用super。
十、JavaSE总结
通过本学期的JavaSE学习,我掌握了Java语言的核心概念和编程技巧。从Java语言的基础语法到面向对象编程,从集合框架到多线程编程,从IO流到泛型,每一个章节都让我对Java有了更深入的理解。
学习心得:
-
实践出真知:理论学习很重要,但必须通过大量编码实践才能真正掌握。
-
理解原理:不仅要知道怎么用,还要知道为什么这么设计,这样才能在实际开发中灵活运用。
-
持续学习:Java生态系统庞大,新版本不断推出,要保持学习的态度。
遇到的主要难点:
-
面向对象思维的转变:从面向过程思维到面向对象思维的转变需要时间。
-
多线程编程:并发编程的概念和问题比较抽象,调试困难。
-
泛型和集合框架:类型安全和性能权衡的理解需要深入思考。
克服方法:
-
多写代码:通过编写大量小程序来巩固概念。
-
阅读源码:分析JDK源码理解内部实现原理。
-
参与项目:在实际项目中应用所学知识,解决真实问题。
JavaSE是Java学习的基础,打好这个基础对于后续的Java EE、Android开发等方向的学习至关重要。希望在未来的学习中能够将这些知识融会贯通,应用到实际开发中。