黄佳豪
第一章:初识 Java 与面向对象程序设计
1.1 Java 概述
核心概念与知识点
- Java 发展历程:诞生于 20 世纪 90 年代,由 Sun Microsystems 公司研发,旨在解决当时电子产品软件跨平台的难题。历经多次版本迭代,从早期专注于桌面应用,到适应互联网兴起大力发展网络编程能力,再到如今在企业级开发、移动开发、大数据等众多领域广泛扎根,每一步都紧跟技术趋势。例如,Java EE 规范为企业级应用构建稳定架构,Android 开发选用 Java 作为主要编程语言,推动智能手机应用爆发式增长。
- Java 语言特点:
- 跨平台性:核心优势,依靠 Java 虚拟机(JVM)实现。Java 源程序被编译成字节码文件(
.class
),字节码不依赖特定硬件与操作系统,能在装有对应 JVM 的各类平台运行,就像一份通用图纸,不同工厂(JVM)按图生产出适配本地的产品。 - 面向对象:将现实世界事物抽象为类和对象,以类封装属性与方法,对象作为类的实例化承载具体数据与行为。如设计 “汽车” 类,有品牌、颜色等属性及启动、加速方法,一辆具体汽车就是 “汽车” 类对象,这种编程范式贴合人类认知习惯,提高代码复用性与可维护性。
- 安全性:强类型检查杜绝非法数据类型操作,内存自动管理机制(垃圾回收)防止内存泄漏与悬空指针,保障程序稳定可靠。例如,访问数组元素时,编译器自动检查索引是否越界,避免内存非法访问。
- 跨平台性:核心优势,依靠 Java 虚拟机(JVM)实现。Java 源程序被编译成字节码文件(
1.2 面向对象程序设计思想
核心概念与知识点
- 类与对象:
- 类:是对一类具有相似特征和行为事物的抽象模板,定义了该类事物共有的属性(成员变量)和方法(成员函数)。如 “学生” 类,涵盖姓名、年龄、成绩等属性,以及学习、考试等方法,类就像建筑蓝图,规划好整体架构。
- 对象:是类的具体实例,通过
new
关键字依据类创建。例如,Student xiaoMing = new Student();
,xiaoMing
便是依据 “学生” 类实例化出的真实个体,拥有类定义的属性初始值,可调用类中的方法,如同依据蓝图盖出的实体房屋。
- 封装:把类的内部数据和操作细节隐藏,对外仅暴露有限接口访问或修改数据。如银行账户类,将余额属性设为私有,配以公开的存款、取款方法,外界只能通过这些方法操作余额,避免随意篡改,保障数据安全,代码逻辑也更清晰,易维护,类似给精密仪器加个带操作按钮的外壳,内部复杂构造不外露。
- 继承:子类可继承父类的非私有属性和方法,用
extends
关键字。例如,定义 “哺乳动物” 为父类,含呼吸、进食通用方法,“猫” 子类继承后,自动拥有这些共性,还能按需添加独特抓老鼠、爬树功能,减少代码重复开发,似家族传承,后代在前人基础上发展。 - 多态:同一操作作用于不同对象呈现不同表现形式。常见有两种实现,一是通过父类引用指向子类对象,如
Animal animal = new Cat();
,调用animal.move();
时,实际执行猫类的move
方法,因运行时依据对象真实类型决策;二是接口实现多态,定义 “绘图” 接口,圆、矩形类实现后,调用 “绘图” 操作各绘对应图形,使程序灵活适应复杂需求,像万能遥控器适配不同电器操作。
1.3 Java 开发环境搭建
核心概念与知识点
- JDK 下载与安装:JDK(Java Development Kit)是 Java 开发核心套件,包含编译、运行 Java 程序必需工具。从 Oracle 官网(或其他合法途径)下载对应操作系统版本,安装过程依提示逐步操作,注意配置环境变量,如在 Windows 系统,需添加
JAVA_HOME
指向 JDK 安装目录,再将%JAVA_HOME%\bin
添加到Path
变量,确保命令行能全局调用 Java 命令,这是开启 Java 编程大门的钥匙,弄错一步,后续开发指令都无法执行。 - 集成开发环境(IDE)选择:常见有 Eclipse、Intellij IDEA 等。Eclipse 开源免费,插件丰富,对初学者友好,社区支持强大,方便快速上手入门;Intellij IDEA 功能强大,智能代码提示、代码分析等高级特性卓越,在大型项目开发效率突出,虽部分功能收费,但教育版免费可用,选择 IDE 如同挑选兵器,依个人习惯与项目需求定,合适的能助力编程事半功倍。
1.4 第一个 Java 程序:HelloWorld!
核心概念与知识点
- 程序结构:一个简单 Java 程序由类定义、
main
方法构成。类是程序基本单元,main
方法是程序入口,如:
java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
- 编译与运行:在命令行,使用
javac
命令编译.java
文件生成.class
字节码文件,如javac HelloWorld.java
;再用java
命令运行字节码,java HelloWorld
,见证代码从文本转化为可执行指令,理解 Java 程序 “先编译后运行” 两步走流程,是后续复杂程序开发调试基础。
1.5 Java 常用开发工具
核心概念与知识点
- 文本编辑器:如 Notepad++、Sublime Text 等,轻量级,适合快速编辑少量代码,有语法高亮显示代码结构,自动缩进辅助排版,虽缺乏大型项目集成管理能力,但启动快、资源占用少,对修改小片段代码、临时调试便捷,像随身携带的小刀,处理简单任务利落。
- 集成开发环境(IDE)详述:
- 代码编辑功能:智能代码补全依上下文预测输入,自动纠错提醒语法错误,代码格式化统一风格,如 Intellij IDEA 能瞬间美化杂乱代码,提升可读性,节省人工排版时间。
- 调试工具:设断点暂停程序,逐行执行观察变量值变化,步入、步出函数深入排查问题,无论是数据错误还是逻辑漏洞,都能精准定位,像给程序安装透视镜,看清运行每一步。
- 项目管理:组织源文件、依赖库,构建项目,如 Maven、Gradle 集成,自动下载管理依赖,确保项目组件协同,避免版本冲突,让大型项目开发井井有条,从架构搭建到代码部署全程护航。
- 个人理解与学习心得:学习 Java 开篇章节时,初次接触面向对象编程思维,我对类与对象的关系深感困惑。反复研读教材示例,动手创建简单类与实例化对象后,才领悟到对象是以类为蓝图的具体实体,类规定了对象的共性。起初,我不理解为何采用面向对象编程,后来知晓其在大型项目开发里,于代码组织、维护及扩展方面优势显著,这才逐渐习惯用该思维分析问题。
-
二、第二章:Java 编程基础
- 核心概念与知识点:
- 数据类型:Java 有基本数据类型(如 int 整型、double 浮点型、char 字符型、boolean 布尔型等)和引用数据类型(类、接口、数组等)。不同数据类型有不同的取值范围和默认值,例如 int 型默认值是 0,boolean 型默认值是 false。
- 变量与常量:变量需要先声明再赋值才能使用,声明格式为数据类型 变量名;常量使用 final 关键字修饰,一旦赋值不能更改,如
final double PI = 3.14159;
。 - 运算符:算术运算符(+、-、*、/、%)、关系运算符(>、<、==、!= 等)、逻辑运算符(&&、||、!)、位运算符(&、|、^ 等)等,要注意运算符的优先级,例如乘法优先级高于加法,必要时使用括号改变运算顺序。
- 流程控制语句:顺序结构、选择结构(if - else、switch - case)和循环结构(for、while、do - while)。例如用 for 循环打印九九乘法表:
-
public class MultiplicationTable { public static void main(String[] args) { for(int i = 1; i <= 9; i++) { for(int j = 1; j <= i; j++) { System.out.print(j + " * " + i + " = " + (i * j) + "\t"); } System.out.println(); } } }
- 2.1变量与常量:变量是程序运行过程中可以改变值的存储单元,需先声明数据类型再赋值,如
int num = 5;
声明一个整型变量 num 并初始化为 5。常量是固定值,用final
修饰,final double PI = 3.14159;
定义圆周率常量 PI,其值不可更改,确保在计算圆周长、面积等用到 PI 时数值稳定。 - 2.2运算符与表达式:涵盖算术运算符(
+
、-
、*
、/
、%
)、关系运算符(>
、<
、==
、!=
、>=
、<=
)、逻辑运算符(&&
、||
、!
)等。表达式由运算符连接操作数构成,如(2 + 3) * 4
是算术表达式,通过运算得出结果 20。逻辑表达式用于条件判断,如age > 18 && gender == 'M'
判断是否为成年男性。 - 2.3选择结构:主要有
if-else
语句和switch
语句。if-else
根据条件执行不同分支,if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); }
判断考试成绩是否及格。switch
用于多分支情况,switch (dayOfWeek) { case 1: System.out.println("星期一"); break; …… }
根据星期几输出对应字符串。 - 2.4循环结构:
while
循环在条件满足时重复执行语句块,while (count < 10) { System.out.println(count); count++; }
打印 0 - 9。do-while
循环先执行一次语句块再判断条件,确保至少执行一次。for
循环常用于已知循环次数的情况,for (int i = 0; i < 5; i++) { System.out.println(i); }
输出 0 - 4,结构紧凑,初始化、条件判断、迭代更新一目了然。 - 2.5方法:方法是完成特定功能的代码块,可带参数、有返回值。如
public static int add(int a, int b) { return a + b; }
定义加法方法,接收两个整型参数,返回它们的和,通过int result = add(3, 4);
调用获取结果 7。 - 2.6数组:数组是相同数据类型元素的有序集合,通过
int[] array = new int[5];
声明并创建可容纳 5 个整型元素的数组,可使用索引访问元素,array[0] = 1;
给第一个元素赋值。还能初始化数组,int[] anotherArray = {1, 2, 3, 4, 5};
简洁地创建并赋值。 - 2.7JVM 中的堆内存与栈内存:栈内存用于存储局部变量、方法调用信息等,遵循后进先出原则,方法调用时入栈,结束时出栈,生命周期与方法执行同步。堆内存用于存储对象实例,对象在堆中创建,通过栈中的引用变量指向堆中的对象,如
Car myCar = new Car();
,myCar 在栈中,实际的 Car 对象在堆中,当对象没有引用指向时,可能被垃圾回收机制回收,释放堆内存空间。 - 个人理解与学习心得:数据类型的种类繁多,一开始容易混淆不同类型的适用场景,特别是在涉及数据存储和运算精度时。通过大量简单的计算练习,才熟练掌握各数据类型转换规则。在流程控制语句学习中,嵌套循环的逻辑较复杂,绘制流程图辅助理解后,对循环执行过程清晰许多。深刻体会到扎实的编程基础对后续复杂程序编写至关重要,每一个语法细节都可能影响程序的正确性。
-
-
三、第三章:面向对象程序设计(基础)
3.1 面向对象的概念
- 对象
- 是对现实世界事物的抽象,具有唯一标识、状态(通过成员变量表示)和行为(通过成员方法表示)。
- 例如,一个 “学生” 对象可以有姓名、年龄、成绩等成员变量作为状态,以及学习、考试等成员方法作为行为。
- 类
- 是对象的模板,定义了对象的属性(成员变量)和行为(成员方法)。
- 比如 “汽车” 类,规定了汽车都具有品牌、颜色、型号等属性和启动、加速、刹车等行为。通过封装隐藏内部细节,外部代码通过类提供的接口访问对象。
-
3.2 面向对象编程
- 类的定义与成员:详细介绍类中成员变量的修饰符(public、private、protected 等,private 用于实现封装,隐藏内部数据),成员方法的重载(方法名相同,参数列表不同,返回值类型可相同或不同),例如:
- public class Calculator {
- private int num1;
- private int num2;
- public Calculator(int n1, int n2)
- { // 构造方法,用于初始化对象
- num1 = n1;
- num2 = n2;
- }
- public int add() {
- return num1 + num2;
- }
- public int add(int n) {
- // 方法重载 return num1 + num2 + n;
- }
- }
- 构造方法:用于创建对象时初始化对象的状态,与类同名,无返回值类型,若未显式定义,编译器会自动生成一个默认无参构造方法,一旦自定义构造方法,默认构造方法就不再自动生成。
- this 关键字:指向当前对象,可用于区分成员变量和局部变量同名情况,在构造方法中调用其他构造方法可提高代码复用性,如
this(参数);
必须放在构造方法首行。
- 抽象类
- 根据需求抽象出合适的类,定义类中的成员变量和成员方法来构建程序逻辑。
- 例如开发一个银行账户管理系统,需要抽象出 “账户” 类,包含账户余额、账户类型等成员变量和存款、取款、查询余额等成员方法。
- 对象交互
- 不同类的对象之间通过方法调用相互协作。
- 如在银行账户管理系统中,“客户” 对象可以调用 “账户” 对象的存款方法来完成存款操作。
-
3.3 构造方法
- 定义与特点
- 特殊的成员方法,名称与类名相同,没有返回值类型(连 void 都不能有)。
- 主要用于在创建对象时初始化对象的状态。
- 例如创建 “三角形” 类,有三条边作为成员变量,构造方法可以接收三条边的长度参数来初始化:
-
java
class Triangle { private double side1; private double side2; private double side3; public Triangle(double s1, double s2, double s3) { side1 = s1; side2 = s2; side3 = s3; } }
- 默认构造方法
- 若未显式定义构造方法,编译器会自动生成一个默认的无参构造方法。但一旦自定义了构造方法,编译器不再自动生成默认无参构造方法。
-
3.4this 关键字
- 区分成员变量与局部变量
- 当成员变量与局部变量同名时,this 用于明确区分,指向成员变量。
- 例如在 “员工” 类中:
- java
-
class Employee { private String name; public Employee(String name) { this.name = name; } }
- 构造方法调用其他构造方法
- 可以在构造方法中用 this (参数列表) 调用其他构造方法,实现代码复用,且必须放在构造方法首行。
- 例如:
-
java
class Rectangle { private int length; private int width; public Rectangle() { this(0, 0); } public Rectangle(int l, int w) { length = l; width = w; } }
3.5static 关键字
- 静态成员变量
- 用 static 修饰的成员变量属于类本身,在内存中只有一份副本,被所有对象共享。
- 例如创建一个 “产品” 类,统计产品数量:
-
java
class Product { private static int count = 0; public Product() { count++; } public static int getCount() { return count; } }
- 静态成员方法
- 也用 static 修饰,不依赖于具体对象,可通过类名直接调用。
- 不能直接访问非静态成员变量和非静态成员方法。
- 例如在工具类中提供一些通用的计算方法:
-
java
class MathUtils { public static int add(int a, int b) { return a + b; } }
3.6 包
- 组织和管理类
- 类似于文件夹,用于将功能相关的类放在一起,便于分类存储和查找,避免类名冲突。
- 包名通常采用反向域名的方式,如 com.example.myproject。
- 例如定义一个类在包中:
-
java
package com.example.myapp; public class MyClass { // 类的内容 }
- 使用其他包中的类
- 可以用完整的类名(包括包名)引用,或者通过 import 关键字导入后直接使用类名。
- 例如:
-
java
import com.example.utils.MyUtils; public class AnotherClass { public void doSomething() { MyUtils.doSomeWork(); } }
-
- 个人理解与学习心得:理解构造方法的作用和初始化过程花费了一些时间,通过对比有构造方法和无构造方法的类实例化差异,明白了它对对象初始状态设定的便利性。成员变量封装时,private 关键字限制了外部直接访问,起初不习惯,后来意识到这有效保护了数据安全,如需访问可通过公有的 getter 和 setter 方法,遵循了面向对象的信息隐藏原则,让代码结构更加清晰。
-
四、第四章:面向对象程序设计(进阶)
- 继承:子类可以继承父类的属性和方法,使用 extends 关键字,子类能复用父类代码,同时可根据自身需求扩展新功能。例如:
- class Animal {
- public void eat() {
- System.out.println("动物吃东西");
- }
- }
- class Dog extends Animal {
- public void bark() {
- System.out.println("狗汪汪叫");
- }
- }
-
这里 Dog 类继承自 Animal 类,拥有 eat 方法同时新增 bark 方法。
- 方法重写:子类重写父类的方法,要求方法签名(方法名、参数列表、返回值类型,子类返回值类型需与父类兼容)完全相同,用于实现子类特有的行为,重写时可使用 @Override 注解来确保正确性。
- 多态:分为编译时多态(方法重载)和运行时多态(通过父类引用指向子类对象实现,调用重写方法时表现出不同行为),如:
- Animal animal = new Dog(); // 父类引用指向子类对象
- animal.eat(); // 调用子类重写后的 eat 方法,表现出多态性
- 抽象类与抽象方法:抽象类用 abstract 修饰,不能实例化,包含抽象方法(只有方法声明,无方法体,也用 abstract 修饰),子类必须重写抽象方法,抽象类为子类提供统一的抽象规范。
-
-
4.1封装:
将数据(属性)和操作这些数据的方法捆绑在一起,隐藏对象的内部细节,对外只提供有限的接口来访问或修改数据。例如,将银行账户类的余额属性设为私有,通过公开的存款、取款方法来操作余额,防止外部随意篡改,保证数据的安全性与完整性,使代码逻辑更清晰,易于维护。 - 4.2
继承:
- 允许创建一个新类(子类)从现有类(父类)获取属性和方法,子类可以复用父类的代码,减少重复开发。比如,定义 “哺乳动物” 为父类,有呼吸、进食等通用方法,“猫” 作为子类继承自 “哺乳动物”,除了拥有通用特性,还能添加自己独特的抓老鼠、爬树等本领,子类在继承基础上可按需扩展功能。
- 4.3
super 关键字:
- 主要用于子类中,一是在子类构造方法中调用父类的构造方法,确保父类的初始化工作先完成,格式为 super (参数列表);二是在子类重写父类方法时,若需要调用父类被重写的原始方法,可用 super. 方法名 (参数列表) 来实现,它帮助子类在拓展功能时与父类紧密协作,又保持自身独特性。
- 4.4
final 关键字:
- 修饰变量时,表示该变量的值一旦赋值就不能再改变,成为常量;修饰方法,意味着子类不能重写该方法,保证方法行为的确定性;修饰类,则该类不能被继承,常用于一些不希望被扩展修改的基础类,维护类结构的稳定性,避免代码过度修改引发错误。
- 4.5
Object 关键字:
- 在 Java 中,所有类都直接或间接继承自 java.lang.Object 类,它是 Java 类层次结构的根。Object 类提供了一些通用方法,如 equals () 用于比较两个对象是否相等,hashCode () 用于获取对象的哈希码,toString () 用于返回对象的字符串表示形式等,这些方法常被子类重写来满足自身需求,保障不同类在基础操作上的一致性。
- 4.6
多态:
- 指同一操作作用在不同对象上可以有不同的表现形式。例如,定义一个 “绘图” 接口,有圆形、矩形等不同图形类实现这个接口,当调用 “绘图” 操作时,圆形绘制圆形图案,矩形绘制矩形图案,多态让程序能根据对象的实际类型灵活执行相应行为,增强代码的适应性,面对复杂需求更游刃有余。
- 4.7
抽象类:
- 用 abstract 修饰,包含抽象方法(只有方法声明,没有方法体)和普通方法。抽象类不能被实例化,它的存在是为子类提供一个通用框架,子类必须继承抽象类并实现抽象方法,促使子类遵循统一设计规范,适用于在一些场景中有共性但具体实现有差异的情况,引导代码的层次化开发。
- 4.8
接口:
- 一种特殊的抽象类型,只包含方法签名、常量和默认方法(Java 8 后新增),接口常用于定义一组规范或契约,实现接口的类必须实现接口内所有方法。例如,“可比较” 接口定义 compareTo () 方法,实现该接口的类就能按统一规则比较大小,不同类依据接口协同工作,让跨类交互更规范、高效,利于构建大型系统。
- 4.9
内部类:
- 定义在另一个类内部的类,分为成员内部类、局部内部类、匿名内部类等。成员内部类可以访问外部类的所有成员,如同外部类的亲密伙伴,方便实现复杂逻辑;局部内部类定义在方法内,作用域受限,常用于临时封装逻辑;匿名内部类则是没有名字的内部类,通常在创建对象时一次性使用,用于简化代码,如为按钮添加点击事件处理时,用匿名内部类快速实现监听器接口,在特定场景下提高代码编写效率。
-
- 个人理解与学习心得:继承、多态概念相互关联,初次接触较难理清其中关系。通过画 UML 类图,直观呈现类之间继承层次和多态调用过程,慢慢掌握精髓。多态的优势在代码扩展维护上尽显,只需改变子类实现,不影响依赖父类的其他代码模块。但编写子类重写方法时,容易忽略 @Override 注解和方法签名规范,导致隐藏的错误,养成严谨遵循语法规则习惯才能用好这些特性。
-
第五章:异常
5.1 异常概述
- 异常的定义:异常是在程序执行过程中出现的意外情况,它会干扰程序的正常流程。异常可以分为两类:
Error
和Exception
。- Error:代表严重的错误,通常是由 Java 虚拟机(JVM)或环境问题引起的,如
OutOfMemoryError
(内存溢出)、StackOverflowError
(栈溢出)。这些错误一般无法在程序中恢复,程序通常会终止。例如,当 Java 程序试图使用超过系统分配的内存时,就会抛出OutOfMemoryError
。 - Exception:这是程序可以处理的异常情况。又可以细分为
Checked Exception
(受检异常)和Unchecked Exception
(非受检异常)。- Checked Exception:这类异常是编译器要求必须处理的异常。它们通常是由于外部因素导致的,如文件不存在、网络连接中断等。例如,
FileNotFoundException
(文件找不到)、SQLException
(数据库操作异常)。在方法中如果可能抛出这类异常,必须使用try - catch
块进行捕获或者在方法签名中使用throws
关键字声明抛出。 - Unchecked Exception:也称为运行时异常(RuntimeException)。这些异常通常是由程序逻辑错误引起的,如
NullPointerException
(空指针异常)、ArrayIndexOutOfBoundsException
(数组越界异常)。编译器不会强制要求处理这类异常,但如果不处理,可能会导致程序崩溃。
- Checked Exception:这类异常是编译器要求必须处理的异常。它们通常是由于外部因素导致的,如文件不存在、网络连接中断等。例如,
- Error:代表严重的错误,通常是由 Java 虚拟机(JVM)或环境问题引起的,如
- 异常的抛出机制:当一个方法执行过程中出现异常情况时,该方法会创建一个异常对象,并将其抛出。异常对象包含了有关异常的信息,如异常类型、异常消息等。如果异常没有在当前方法中被捕获,它会沿着方法调用栈向上传播,直到被捕获或者导致程序终止。
-
5.2 异常处理
try - catch 块
- 基本结构:
try
块用于包裹可能会抛出异常的代码。catch
块紧跟在try
块之后,用于捕获并处理try
块中抛出的异常。一个try
块可以有多个catch
块,每个catch
块用于处理一种特定类型的异常。例如:
- 基本结构:
-
java
try { // 可能会抛出异常的代码 int result = 10 / 0; } catch (ArithmeticException e) { // 处理算术异常 System.out.println("除数不能为零:" + e.getMessage()); }
- 异常类型匹配:
catch
块按照从上到下的顺序进行匹配,当异常对象的类型与catch
块中声明的异常类型匹配时,对应的catch
块中的代码会被执行。所以,在编写多个catch
块时,应该将子类异常类型放在前面,父类异常类型放在后面,以避免子类异常被父类异常捕获。 - finally 块
- 执行时机:
finally
块是可选的,它跟在try - catch
块之后。无论try
块中是否抛出异常,finally
块中的代码都会被执行。finally
块通常用于释放资源,如关闭文件流、数据库连接等。例如:
- 执行时机:
-
java
try { FileInputStream fis = new FileInputStream("file.txt"); // 读取文件操作 } catch (FileNotFoundException e) { // 处理文件不存在的异常 } finally { if (fis!= null) { try { fis.close(); } catch (IOException e) { // 处理关闭文件流时可能出现的异常 } } }
- throws 关键字
- 方法声明中的使用:用于在方法签名中声明该方法可能抛出的异常。这样,调用该方法的代码就知道需要处理这些异常。例如:
-
public void readFile(String file) throws FileNotFoundException { FileInputStream fis = new FileInputStream(file); // 读取文件操作 }
- 异常传播:如果一个方法声明了
throws
异常,那么在调用这个方法的方法中,要么使用try - catch
块捕获并处理这个异常,要么也在自己的方法签名中使用throws
关键字继续向外传播这个异常。 -
5.3 异常进阶
- 自定义异常
- 继承关系:自定义异常通常是继承自
Exception
类或者它的子类(如果是运行时异常则继承自RuntimeException
)。例如,创建一个表示业务逻辑中库存不足的异常: - java
- 继承关系:自定义异常通常是继承自
- 抛出时机:在程序的业务逻辑中,当满足特定条件(如库存数量小于购买数量)时,就可以抛出自定义异常。例如:
- 异常链
- 构建方式:在捕获一个异常后,将其包装在另一个异常中并重新抛出,就形成了异常链。这有助于在异常传播过程中保留原始异常的信息,同时添加新的上下文信息。例如
-
java
try { // 一些可能导致异常的操作 } catch (OriginalException e) { throw new WrappedException("在执行某个操作时出现问题", e); }
- 获取原始异常信息:在处理异常链时,可以通过
getCause()
方法获取原始异常,以便更好地分析问题的根源。例如: -
java
try { // 调用可能抛出异常链的方法 } catch (WrappedException we) { Exception originalCause = we.getCause(); System.out.println("原始异常信息:" + originalCause.getMessage()); }
第六章:Java 常用类
- 核心概念与知识点:
- 字符串类 String:不可变对象,一旦创建不能修改,提供丰富操作方法,如连接(concat)、截取(substring)、查找(indexOf)等,例如:
-
java
String str = "Hello"; String newStr = str.concat(" World"); // 生成新字符串 "Hello World"
- StringBuffer 和 StringBuilder:可变字符序列,用于频繁修改字符串场景,StringBuffer 线程安全但效率稍低,StringBuilder 非线程安全效率高,常用方法有 append(追加字符)、insert(插入字符)等,如:
-
java
StringBuilder sb = new StringBuilder("Start"); sb.append(" - Append text"); // 修改原对象,变为 "Start - Append text"
- 包装类:基本数据类型对应的包装类(如 Integer、Double 等),实现基本类型与引用类型转换,自动装箱(自动将基本类型转为包装类)和自动拆箱(反之)方便操作,同时包装类提供一些实用方法,如 Integer.parseInt () 可将字符串解析为整型。
- 日期时间类:旧版 Date 类有诸多不便,Java 8 引入 LocalDate、LocalTime、LocalDateTime 等新 API,方便日期时间操作,如获取当前日期
LocalDate.now()
,格式化日期时间可用 DateTimeFormatter,例如: -
java
LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formatted = now.format(formatter); System.out.println(formatted);
-
6.1 包装类
- 概念
- 为基本数据类型提供对象的包装,使基本数据类型可以像对象一样参与操作,如存储在集合中。
- 对应关系:byte - Byte、short - Short、int - Integer、long - Long、float - Float、double - Double、char - Character、boolean - Boolean。
- 知识点
- 装箱与拆箱
- 装箱:将基本数据类型转换为包装类对象。例如,自动装箱可以使用
Integer i = 5;
,编译器会自动将5
转换为Integer
对象。 - 拆箱:把包装类对象转换为基本数据类型。例如,自动拆箱可以使用
int n = i;
,编译器会自动调用i
的拆箱方法获取基本值。
- 装箱:将基本数据类型转换为包装类对象。例如,自动装箱可以使用
- 常用方法
- 以 Integer 为例
parseInt(String s)
:将字符串形式的数字转换为整型。例如,int num = Integer.parseInt("123");
。valueOf(String s)
:将字符串转换为对应的包装类对象,也参与自动装箱。例如,Integer numObj = Integer.valueOf("456");
。
- 其他包装类也有类似用于数据类型转换、取值等的方法,如
Double.parseDouble
、Boolean.parseBoolean
等。
- 以 Integer 为例
- 装箱与拆箱
-
6.2 String 类概述
- 概念
- 用于表示字符序列,是不可变的对象,一旦创建,内容不能被修改。
- 字符串字面量池:Java 维护的一个存储字符串字面量的区域,相同的字符串字面量在池中只有一份,提高内存利用效率。
- 知识点
- 不可变性示例:当执行
String str = "Hello"; str = str + " World";
时,实际上是创建了一个新的String
对象,原"Hello"
字符串对象依然存在,只是str
引用指向了新对象。 - 常用方法
length()
:返回字符串的长度。例如,String s = "abc"; int len = s.length();
,len
的值为3
。charAt(int index)
:返回指定索引处的字符。例如,char c = s.charAt(1);
,c
的值为b
。substring(int start, int end)
:截取从start
(包含)到end
(不包含)的子字符串。例如,String sub = s.substring(1, 3);
,sub
的值为bc
。indexOf(String str)
:查找子字符串首次出现的位置。例如,String text = "abcde"; int pos = text.indexOf("cd");
,pos
的值为2
。equals(String anotherString)
:比较两个字符串内容是否相等。例如,String s1 = "abc"; String s2 = "ABC"; s1.equals(s2)
返回false
,s1.equalsIgnoreCase(s2)
返回true
(忽略大小写比较)。
- 不可变性示例:当执行
-
6.3 StringBuffer 类与 StringBuilder 类
- 概念
- 都是可变的字符序列类,用于处理需要频繁修改字符串内容的情况,相比
String
类在性能上有优势。 StringBuffer
是线程安全的,StringBuilder
是非线程安全的,在单线程环境下StringBuilder
性能更高。
- 都是可变的字符序列类,用于处理需要频繁修改字符串内容的情况,相比
- 知识点
- 可变字符串原理:内部通过字符数组实现,对字符串的修改操作(如追加、插入、删除)是在原有字符数组上进行,避免了像
String
类那样频繁创建新对象。 - StringBuffer 常用方法
append(String str)
:在原有字符串末尾追加内容。例如,StringBuffer sb = new StringBuffer("Hello"); sb.append(" World");
,结果为Hello World
。insert(int offset, String str)
:在指定位置插入字符串。例如,sb.insert(5, "Java ");
,结果为Hello Java World
。delete(int start, int end)
:删除指定范围内的字符。例如,sb.delete(5, 10);
,结果为Hello World
。
- StringBuilder 常用方法:与
StringBuffer
的方法类似,包括append
、insert
、delete
等操作,只是在多线程环境下需要注意其非线程安全的特性。
- 可变字符串原理:内部通过字符数组实现,对字符串的修改操作(如追加、插入、删除)是在原有字符数组上进行,避免了像
- 概念
- 用于处理日期和时间相关的操作,Java 提供了多种日期时间类来满足不同的需求。
- 知识点
- Date 类
- 表示特定瞬间,精确到毫秒。例如,
Date now = new Date();
可以获取当前日期和时间,但很多方法已过时。 - 常与
SimpleDateFormat
类一起使用来格式化日期。例如,SimpleDateFormat sdf = new SimpleDateFormat("yyyy - MM - dd HH:mm:ss"); String dateStr = sdf.format(now);
可以将日期格式化为指定的字符串形式。
- 表示特定瞬间,精确到毫秒。例如,
- Calendar 类
- 抽象类,提供了丰富的方法来获取和设置日期时间的各个字段(年、月、日、时、分、秒等)。
- 通过
Calendar.getInstance()
获取实例。例如,Calendar cal = Calendar.getInstance(); int year = cal.get(Calendar.YEAR);
可以获取当前年份。 - 可以进行日期时间的计算和设置。例如,
cal.set(Calendar.MONTH, Calendar.JANUARY);
可以将月份设置为一月。
- Java 8 新日期时间 API
- LocalDate:专注于日期部分。例如,
LocalDate today = LocalDate.now();
获取当前日期。可以进行日期的比较、加减等操作,如LocalDate tomorrow = today.plusDays(1);
。 - LocalTime:侧重于时间部分。例如,
LocalTime nowTime = LocalTime.now();
获取当前时间。也支持时间的运算,如LocalTime newTime = nowTime.plusHours(1);
。 - LocalDateTime:涵盖日期和时间。例如,
LocalDateTime nowDateTime = LocalDateTime.now();
获取当前日期和时间。能进行复杂的日期时间操作,如LocalDateTime futureDateTime = nowDateTime.plusDays(2).plusHours(3);
。 - 支持时区处理。例如,
ZoneId zone = ZoneId.of("Asia/Shanghai"); LocalDateTime shanghaiTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).withZoneSameAs(zone).toLocalDateTime();
可以将日期时间转换到指定时区。
- LocalDate:专注于日期部分。例如,
- Date 类
-
6.5 其他常用类
- 概念
- 包括一些在数学计算、随机数生成、系统操作等方面常用的类。
- 知识点
- Math 类
- 提供了大量静态数学方法,无需实例化。例如,
Math.sqrt(9)
计算平方根,结果为3
;Math.pow(2, 3)
计算指数幂,结果为8
;Math.max(5, 7)
返回最大值,结果为7
。 - 涵盖算术、三角、指数等多种数学运算方法,如
sin
、cos
、tan
等三角函数,log
、exp
等对数和指数函数。
- 提供了大量静态数学方法,无需实例化。例如,
- Random 类
- 用于生成随机数。例如,
Random rand = new Random(); int randomNum = rand.nextInt(10);
可以生成0
到9
之间的随机整数。 - 可以设置种子值来控制随机数序列。例如,
Random seededRand = new Random(1234);
,相同种子生成的随机数序列是相同的。
- 用于生成随机数。例如,
- System 类
- 提供与系统交互的方法。例如,
System.out.println()
用于向控制台输出信息;System.currentTimeMillis()
获取当前系统时间的毫秒数,常用于计时,如计算代码执行时间;System.exit(0)
用于正常终止程序。
- 提供与系统交互的方法。例如,
- Math 类
-
6.4 时间与日期相关类
- 概念
- 用于处理日期和时间相关的操作,Java 提供了多种日期时间类来满足不同的需求。
- 知识点
- Date 类
- 表示特定瞬间,精确到毫秒。例如,
Date now = new Date();
可以获取当前日期和时间,但很多方法已过时。 - 常与
SimpleDateFormat
类一起使用来格式化日期。例如,SimpleDateFormat sdf = new SimpleDateFormat("yyyy - MM - dd HH:mm:ss"); String dateStr = sdf.format(now);
可以将日期格式化为指定的字符串形式。
- 表示特定瞬间,精确到毫秒。例如,
- Calendar 类
- 抽象类,提供了丰富的方法来获取和设置日期时间的各个字段(年、月、日、时、分、秒等)。
- 通过
Calendar.getInstance()
获取实例。例如,Calendar cal = Calendar.getInstance(); int year = cal.get(Calendar.YEAR);
可以获取当前年份。 - 可以进行日期时间的计算和设置。例如,
cal.set(Calendar.MONTH, Calendar.JANUARY);
可以将月份设置为一月。
- Java 8 新日期时间 API
- LocalDate:专注于日期部分。例如,
LocalDate today = LocalDate.now();
获取当前日期。可以进行日期的比较、加减等操作,如LocalDate tomorrow = today.plusDays(1);
。 - LocalTime:侧重于时间部分。例如,
LocalTime nowTime = LocalTime.now();
获取当前时间。也支持时间的运算,如LocalTime newTime = nowTime.plusHours(1);
。 - LocalDateTime:涵盖日期和时间。例如,
LocalDateTime nowDateTime = LocalDateTime.now();
获取当前日期和时间。能进行复杂的日期时间操作,如LocalDateTime futureDateTime = nowDateTime.plusDays(2).plusHours(3);
。 - 支持时区处理。例如,
ZoneId zone = ZoneId.of("Asia/Shanghai"); LocalDateTime shanghaiTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).withZoneSameAs(zone).toLocalDateTime();
可以将日期时间转换到指定时区。
- LocalDate:专注于日期部分。例如,
- Date 类
-
6.5 其他常用类
- 概念
- 包括一些在数学计算、随机数生成、系统操作等方面常用的类。
- 知识点
- Math 类
- 提供了大量静态数学方法,无需实例化。例如,
Math.sqrt(9)
计算平方根,结果为3
;Math.pow(2, 3)
计算指数幂,结果为8
;Math.max(5, 7)
返回最大值,结果为7
。 - 涵盖算术、三角、指数等多种数学运算方法,如
sin
、cos
、tan
等三角函数,log
、exp
等对数和指数函数。
- 提供了大量静态数学方法,无需实例化。例如,
- Random 类
- 用于生成随机数。例如,
Random rand = new Random(); int randomNum = rand.nextInt(10);
可以生成0
到9
之间的随机整数。 - 可以设置种子值来控制随机数序列。例如,
Random seededRand = new Random(1234);
,相同种子生成的随机数序列是相同的。
- 用于生成随机数。例如,
- System 类
- 提供与系统交互的方法。例如,
System.out.println()
用于向控制台输出信息;System.currentTimeMillis()
获取当前系统时间的毫秒数,常用于计时,如计算代码执行时间;System.exit(0)
用于正常终止程序。
- 提供与系统交互的方法。例如,
- 个人理解与学习心得:学习 Java 常用类这章,收获满满。包装类让基本数据类型能像对象一样灵活参与编程,自动装箱拆箱虽方便但得小心性能陷阱。String 类不可变,字面量池很精妙,可变的 StringBuffer 和 StringBuilder 帮大忙,多线程、单线程操作各有适用。时间日期类从老旧 Date、复杂 Calendar 到简洁强大的 Java 8 新 API,处理时间得心应手。Math 类提供数学运算便利,Random 类生成随机数有趣又实用,System 类连接程序与系统,这些常用类让 Java 编程轻松不少,也深知选对工具才能高效开发。
- Math 类
-
什么是受检异常和非受检异常?
如何在Java中处理异常?
自定义异常类需要注意什么?
-
-