【JAVA】基础(一)
文章目录
- 一、编程基础
- (一) this关键字
- 1. 访问当前对象的属性、方法
- 2. 解决变量名冲突
- (二) 成员变量与局部变量的区别
- (三) 包与API
- (四) String类(字符串处理)
- (五) ArrayList集合(可变数据容器)
- 遍历删除防bug
- (六) static关键字(静态修饰符)
- (七) 单例设计模式
- 二、面向对象三大特性
- (一) 封装与实体类(JavaBean)
- (二) 继承(extends)
- (三) 多态(面向对象三大特征之三)
- 三、基础工具类
- (一) final关键字(最终修饰符)
- (二) 抽象类(abstract)
- 模板方法设计模式(抽象类的典型应用)
- (三) 接口(interface)
- JDK8+接口新增3种方法
- (四) 内部类(类中类,封装子事物)
- (五) 枚举(特殊类)
- (六) 泛型(参数化类型)
- 1. 三种形式
- 一、泛型类
- 二、泛型接口(含类型变量的接口)
- 三、泛型方法(含类型变量的方法)
- 2. 泛型通配符与上下限
- (七) 常用API(java.lang包核心)
- 1. Object类(所有类的祖宗类)
- 2. 克隆的两种方式
- 3. Objects工具类
- 4. 包装类(基本类型→对象)
- 5. StringBuilder(可变字符串)
- 6. StringJoiner(JDK8+,简化拼接)
- (八) 基础工具类
- 1. Math(数学工具类)
- 2. System(系统工具类)
- 3. Runtime(运行环境类)
- (九) BigDecimal(高精度小数)
- (十) 日期与时间API(JDK8+)
- (十一) Arrays(数组工具类)
- (十二) Lambda表达式(简化匿名内部类)
- (十三) 异常(程序错误处理)
- 一、异常体系(核心层级)
- 二、异常的处理方式
- 三、自定义异常
- 四、异常的核心作用
- (十四) File类(文件/文件夹操作)
一、编程基础
(一) this关键字
1. 访问当前对象的属性、方法
执行原理:
- 调用对象方法时,JVM自动将对象地址传递给
this。 - 通过
this可访问当前对象的成员变量和方法。
public class Student {String name;public void printThis() { System.out.println(this); // 输出当前对象的地址(如com.itheima.Student@776ec8df)}
}
// 测试
Student s1 = new Student();
s1.printThis(); // this指向s1
Student s2 = new Student();
s2.printThis(); // this指向s2
2. 解决变量名冲突
当成员变量与局部变量名一致时,用this区分成员变量(否则优先使用局部变量):
public class Student {double score; // 成员变量// 参数名score与成员变量名冲突public void checkPass(double score) {// this.score 指成员变量,score指参数if (this.score >= score) {System.out.println("恭喜考上哈佛!");} else {System.out.println("未考上");}}
}
(二) 成员变量与局部变量的区别
| 区别维度 | 成员变量(类中方法外) | 局部变量(方法内/参数) |
|---|---|---|
| 类中位置 | 类中,方法外部 | 方法内部、方法参数、代码块中 |
| 初始化值 | 有默认值(无需手动初始化) | 无默认值,使用前必须赋值 |
| 内存存储位置 | 堆内存(随对象存储) | 栈内存(随方法调用存储) |
| 作用域 | 整个对象(类内可访问) | 仅在所属代码块(如方法)内有效 |
| 生命周期 | 与对象共存亡(对象销毁则消失) | 随方法调用而生,方法执行结束则消失 |
(三) 包与API
- API定义:即应用程序编程接口,是他人编写的可直接调用的程序,用于快速解决开发问题。
- 包的核心作用:类似文件夹,用于分门别类管理程序,方便维护。
- 包的使用规则:
- 同包内程序可直接调用;
- 异包程序需导包(语法import 包名.类名;);
- 调用不同包下同名类时,一个用import导入,另一个需带完整包名访问(如
com.itheima.A a = new com.itheima.A();)
(四) String类(字符串处理)
- 核心作用:创建对象封装字符串数据,并提供方法处理字符串(如截取、比较)。
- 对象创建方式:
- 双引号定义:
String 变量名 = "字符串内容";存储于字符串常量池(堆内存中),同内容仅存1份; - new + 构造器:
new String(参数)(支持空白、字符串、字符 / 字节数组),每 new 一次在堆内存生成新对象。
- 双引号定义:
- 关键特性:String对象不可变,"修改"实际是生成新对象。
- 比较方式:推荐用 equals() (比内容),==仅比地址(易出bug,仅基本类型用)。
| 构造器 | 说明 |
|---|---|
| public String() | 创建空白字符串(无内容) |
| public String(String original) | 根据传入字符串创建对象 |
| public String(char[] chars) | 根据字符数组创建对象 |
| public String(byte[] bytes) | 根据字节数组创建对象(按ASCII解析) |
| 方法名 | 说明 |
|---|---|
| public int length() | 获取字符串长度(字符个数) |
| public char charAt(int index) | 获取指定索引处的字符(索引从0开始) |
| public char[] toCharArray() | 将字符串转为字符数组返回 |
| public boolean equals (Object obj) | 比较两个字符串内容是否相同(推荐) |
| public boolean equalsIgnoreCase(String s) | 比较内容(忽略大小写) |
| public String substring (int begin, int end) | 截取字符串(包前不包后) |
| public String substring(int begin) | 从begin索引截取到字符串末尾 |
| public String replace (CharSequence old, CharSequence new) | 替换字符串中的旧值为新值 |
| public boolean contains(CharSequence s) | 判断字符串是否包含指定内容 |
| public boolean startsWith(String prefix) | 判断字符串是否以指定内容开头 |
| public String[] split(String regex) | 按指定规则分割字符串,返回字符串数组 |
(五) ArrayList集合(可变数据容器)
ArrayList是最常用的可变数据容器,无参构造创建空集合(new ArrayList<>())
| 方法名 | 说明 |
|---|---|
| public boolean add(E e) | 末尾添加元素,返回是否成功 |
| public void add(int index, E e) | 指定索引插入元素(索引需合法) |
| public E get(int index) | 获取指定索引的元素 |
| public int size() | 返回集合中元素个数(类似数组length) |
| public E remove(int index) | 删除指定索引元素,返回被删元素 |
| public boolean remove(Object o) | 删除指定内容的元素,返回是否成功 |
| public E set(int index, E e) | 修改指定索引元素,返回旧元素 |
遍历删除防bug
- 删除后索引-1
每次删除元素后,将循环索引减1,避免下一次遍历跳过元素:
for (int i = 0; i < list.size(); i++) { if ("黑马".equals(list.get(i))) {list.remove(i);i--; // 索引回退,避免漏删}
}
- 从后向前遍历
从集合末尾开始遍历,删除元素不影响前面元素的索引:
for (int i = list.size() - 1; i >= 0; i--) { if ("黑马".equals(list.get(i))) { list.remove(i);}
}
(六) static关键字(静态修饰符)
实现"数据/方法共享",摆脱对象依赖。
- 成员变量分类:
| 类型 | 修饰符 | 归属 | 使用方式 | 特点(核心区别) |
|---|---|---|---|---|
| 类变量 | static | 类 | 类名.类变量(推荐) 对象.类变量(不推荐) | 与类一起加载,内存中仅1份,所有对象共享 |
| 实例变量 | 无 | 对象 | 对象.实例变量 | 每个对象1份,对象间数据独立 |
- 成员方法分类:
| 类型 | 修饰符 | 归属 | 使用方式 | 访问权限(核心规则) |
|---|---|---|---|---|
| 类方法 | static | 类 | 类名.类方法(推荐) | 仅能直接访问类成员(类变量、类方法), 不能访问实例成员、不能用this |
| 实例方法 | 无 | 对象 | 对象.实例方法 | 可直接访问类成员和实例成员,能用this |
- 代码块(static与实例代码块):
| 类型 | 格式 | 执行时机 | 作用 |
|---|---|---|---|
| 静态代码块 | static {} | 类加载时执行(仅1次) | 初始化类变量(如加载配置文件) |
| 实例代码块 | {} | 每次创建对象时执行(在构造器前) | 初始化实例变量(补充构造器功能) |
(七) 单例设计模式
核心目标:确保类仅能创建1个对象,避免内存浪费(如任务管理器)。
核心实现逻辑:私有构造器(禁外部new)、类变量存唯一实例、类方法返回唯一实例。
两种实现方式:
- 饿汉式:类加载时创实例,线程安全但可能浪费内存;
public class Singleton { // 1. 私有构造器private Singleton() {} // 2. 类变量存储唯一实例 private static Singleton instance = new Singleton(); // 3. 类方法返回实例public static Singleton getInstance() { return instance; }
}
- 懒汉式:调用方法时创实例(延迟加载),节省内存但非线程安全。
public class Singleton { private Singleton() {}private static Singleton instance; // 初始为nullpublic static Singleton getInstance() { if (instance == null) { // 为空时才创建instance = new Singleton();}return instance;}
}
二、面向对象三大特性
(一) 封装与实体类(JavaBean)
封装作用:数据安全与解耦
专用于存储数据的类,需满足:属性私有、方法公开,实现“数据与业务逻辑分离”。
public class Student { // 1. 私有成员变量private String name; private double chinese;// 2. 无参构造器 public Student() {}// 3. get/set方法 public String getName() {return name;}public void setName(String name) { this.name = name; // 用this解决变量冲突}public double getChinese() {return chinese;}public void setChinese(double chinese) {this.chinese = chinese;}
}
(二) 继承(extends)
- 核心作用:建立父子类关系,子类复用父类**非私有成员,**减少重复代码。
- 定义语法:
public class 子类名 extends 父类名 {} - 对象创建:子类对象由"子类+父类"共同初始化(父类成员先初始化,子类后初始化)。
权限修饰符(控制成员访问范围):
| 修饰符 | 本类 | 同包类 | 子类(异包) | 任意类 |
|---|---|---|---|---|
| private | √ | × | × | × |
| 缺省 | √ | √ | × | × |
| protected | √ | √ | √ | × |
| public | √ | √ | √ | √ |
-
方法重写:
子类重写父类方法需满足"方法名/参数列表一致、权限≥父类、返回值一致或更小",加@Override校验; -
继承限制:Java
单继承(1个直接父类)、支持多层继承,Object是所有类的祖宗类; -
构造器调用:子类构造器必先调用父类构造器(默认super(),父类无无参构造器需手动写super(参数));
| 关键字 | 核心作用 | 访问成员变量 | 访问成员方法 | 访问构造器 |
|---|---|---|---|---|
| this | 本类对象引用 | this.本类变量 | this.本类方法(…) | this(…)(调用本类其他构造器) |
| super | 父类存储空间标识 | super.父类变量(子父类重名时用) | super.父类方法(…) (调用父类方法) | super(…)(调用父类构造器) |
(三) 多态(面向对象三大特征之三)
“对象多态、行为多态”
三个前提:
- 存在继承或实现关系(子类继承父类,或类实现接口);
- 子类(或实现类)重写了父类(或接口)的方法;
- 父类(或接口)引用指向子类(或实现类)对象(如 Parent p = new Child();)。
核心表现是“编译看左,运行看右”,
属性不参与多态,无论编译还是运行阶段,通过父类引用访问的属性均为父类中声明的属性
好处与问题:
- 解耦(子类对象灵活切换)、扩展性强(父类形参接收所有子类);
- 但无法直接调用子类独有方法;
解决方案:
| 转换类型 | 语法 | 适用场景 | 特点 |
|---|---|---|---|
| 自动转换 | 父类类型 变量 = 子类对象; | 多态的初始化(父类引用指向子类) | 无需手动操作,安全 |
| 强制转换 | 子类类型 变量 = (子类类型)父类变量; | 调用子类独有方法 | 需手动操作,存在安全风险 |
风险:
- 若父类引用的真实对象类型与强转后的类型不一致,运行时会报ClassCastException(类型转换异常)。
示例:
People p = new Teacher();
Student s = (Student)p;
//运行报错,Teacher不能转Student
解决方案:
- 强转前用 instanceof 判断对象真实类型
- 语法:
对象 instanceof 类型(返回boolean)
示例:
if (p instanceof Student) {Student s = (Student)p;s.test(); // 安全调用子类独有方法
} else if (p instanceof Teacher) { Teacher t = (Teacher)p;t.teach();
}
三、基础工具类
(一) final关键字(最终修饰符)
- 常量:
static final修饰,全大写(多单词下划线连接),编译期"宏替换",用于存储系统配置。
| 修饰对象 | 效果 | 示例 |
|---|---|---|
| 类 | 类成为"最终类",不能被继承 | final class A { } class B extends A { }报错 |
| 方法 | 方法成为"最终方法",不能被重写 | class C { public final void test() {} } // 子类重写test()报错 |
| 变量 | 变量仅能赋值1次(赋值后不可修改) | final int a = 10; a = 20; //报错 |
注意:
基本类型变量:存储的数据值不可修改;
引用类型变量:存储的对象地址不可修改,但对象内部的属性可修改。
示例:
final Student s = new Student();
s.setName("张三"); // 允许(修改对象属性)
s = new Student(); // 报错(修改地址)
(二) 抽象类(abstract)
- 抽象类是 abstract 修饰,仅有方法签名,无方法体(需子类实现)
- 用于抽取子类共性、定义规范,支持多态扩展。
- 有抽象方法的类必是抽象类,不能实例化
- 子类需重写所有抽象方法(否则子类也为抽象类);
// 抽象类 示例:
public abstract class Animal { // 抽象方法(无方法体)public abstract void cry();// 抽象类可包含普通成员(变量、方法、构造器)private String name;public void setName(String name) {this.name = name;}
}
模板方法设计模式(抽象类的典型应用)
重复代码抽为模板方法,差异化逻辑抽为抽象方法由子类实现
// 第一步:定义抽象类,包含两类方法
public abstract class Employee {private String name;private int age;// (1)模板方法:封装重复代码(如流程控制),用final修饰(防止子类重写破坏流程)public final void printIntro() {System.out.println("姓名:" + name + ",年龄:" + age);// 第三步:调用模板方法,自动执行重复代码+子类差异化逻辑printSpecialInfo();}// (2)抽象方法:定义差异化逻辑,由子类重写实现public abstract void printSpecialInfo();
}// 第二步:子类继承抽象类,重写抽象方法
// 子类1:教师
public class Teacher extends Employee {private String skill;@Overridepublic void printSpecialInfo() {System.out.println("技能:" + skill);}
}// 子类2:咨询师
public class Consultant extends Employee {private int answerCount;@Overridepublic void printSpecialInfo() {System.out.println("解答问题数:" + answerCount);}
}
(三) 接口(interface)
- 基础特性:JDK8前仅含"常量(默认public static final) + 抽象方法( 默认 public abstract )";类用 implements 实现,支持多实现,需重写所有抽象方法;
- 核心好处:弥补类单继承不足,支持面向接口编程(灵活切换实现类);
- JDK8+新增方法:默认方法( default, 实现类对象调用)、静态方法(static,接口名调用)、私有方法(private,JDK9+,仅接口内调用);
- 多继承与冲突:接口可多继承,若父接口默认方法同名则冲突;类实现多接口遇同名默认方法,需重写解决,且优先使用父类同名方法。
public interface Driver {// 常量(默认public static final)String LICENSE_TYPE = "C1";// 抽象方法(默认public abstract)void drive();
}
- 接口不能直接实例化,但可通过"接口引用指向实现类对象"支持多态。
// 实现多个接口
public class A implements Driver, Singer {@Overridepublic void drive() {System.out.println("开车");}@Overridepublic void sing() {System.out.println("唱歌");}
}// 多态使用
Driver d = new A();
d.drive(); // 执行A的drive()
JDK8+接口新增3种方法
| 方法类型 | 修饰符 | 调用方式 | 作用 |
|---|---|---|---|
| 默认方法 | default | 实现类对象调用 | 提供默认实现,子类可重写 |
| 静态方法 | static | 接口名调用(如 A.test3() ) | 提供工具方法,与实现类解耦 |
| 私有方法 | private | 仅接口内部调用(JDK9+) | 抽取接口内重复代码,隐藏逻辑 |
示例:
public interface A { // 默认方法 default void test1() {System.out.println("默认方法");test2(); // 调用私有方法}// 私有方法(JDK9+)private void test2() { System.out.println("接口内部私有方法");}// 静态方法 static void test3() {System.out.println("静态方法,接口名调用");}
}// 调用
A.test3(); // 静态方法调用
A a = new AImpl();
a.test1(); // 默认方法调用
一个接口可继承多个接口(用extends关键字),子类实现该接口时需重写所有父接口的抽象方法。
示例:
// 父接口A、B
interface A { void test1(); }
interface B { void test2(); }// 接口C继承A、B
interface C extends A, B {}// 实现类需重写test1()和test2()
class CImpl implements C { @Override public void test1() {}@Override public void test2() {}
}
注意:
- 方法签名冲突:
- 接口多继承时,若父接口有同名抽象方法,不冲突(仅需重写1次);若有同名默认方法,冲突(不支持多继承);
- 类实现多个接口时,若接口有同名默认方法,实现类需重写该方法解决冲突。
- 父类与接口默认方法优先级:
类同时继承父类和实现接口,若两者有同名默认方法,优先使用父类的方法。
(四) 内部类(类中类,封装子事物)
内部类是类的五大成分之一(成员变量、方法、构造器、内部类、代码块),用于封装"仅属于外部类的子事物",避免单独设计类造成冗余。
| 类型 | 核心特点与用法 |
|---|---|
| 成员内部类 | 无static,属外部类实例; 需先创建外部类对象,再创建内部类对象( new Outer().new Inner() ); 可直接访问外部类实例/静态成员; 若需明确指向外部类对象,用外部类名 .this (如 Outer.this. 属性 ) |
| 静态内部类 | 有static,属外部类本身;直接通过外部类名创建( new Outer.Inner() ); 仅能访问外部类静态成员,不能直接访问实例成员 |
| 局部内部类 | 定义在方法/代码块/构造器内,作用域仅限当前执行体,了解即可。 |
| 匿名内部类 | 无类名的子类匿名对象;创建后立即生成对象 语法 new 类 / 接口 ( 参数 ){ 重写方法 }; 核心用于作为方法参数传递,简化代码(无需单独定义子类)。 |
public class Outer { // 成员内部类 public class Inner { public void test() { System.out.println("成员内部类方法");}}
}
public class Outer { public static String schoolName = "黑马"; // 静态内部类 public static class Inner { public void test() { System.out.println(schoolName); // 直接访问外部类静态成员}}
}
(五) 枚举(特殊类)
枚举用于表示"一组固定的、有限的信息"(如性别、季节),本质是不可继承的最终类,内部存储常量对象。
修饰符 enum 枚举类名 {常量1, 常量2, 常量3; // 第一行必须是枚举常量(本质是枚举类的对象)// 其他成员(属性、方法、构造器)
}
注意:
- 枚举类是final 的,
不能被继承;构造器必为private ,对外不能创建对象(仅内部常量是对象);- 编译器自动新增方法:values() (返回所有枚举常量数组)、valueOf(String name) (按名称获取枚举常量);
- 所有枚举类默认继承 java.lang.Enum 类,可直接使用 name() 、ordinal() 等方法。
- 作为方法参数,约束参数值范围(避免传入无效值,比用常量更安全)。
示例:
// 仅能传入Gender.BOY或Gender.GIRL
public static void checkGender(Gender gender) { switch (gender) { case BOY: System.out.println("展示男性内容"); break; case GIRL: System.out.println("展示女性内容"); break;}
}
(六) 泛型(参数化类型)
-
核心作用:
定义类/接口/方法时声明类型变量(如),编译期约束数据类型,避免强制类型转换及异常,提升代码复用性。 -
本质:将具体数据类型作为"参数"传给类型变量(如ArrayList中String是传给 的参数);
-
好处:编译期校验类型,减少运行时异常;无需手动强转,代码更简洁。
1. 三种形式
一、泛型类
修饰符 class 类名<T> (如ArrayList),复用类适配多类型;
(类型变量建议用大写字母:E-元素、T-类型、K-键、V-值)
public class MyList<E> { private E[] array; // 存储E类型的数据 public void add(E e) { ... } // 添加E类型元素 public E get(int index) { ... } // 返回E类型元素
}// 使用:指定E为String
MyList<String> list = new MyList<>();
list.add("java");
String s = list.get(0); // 无需强转
二、泛型接口(含类型变量的接口)
修饰符 interface 接口名<T> (如Data),实现时指定具体类型;
// 泛型接口:定义数据操作规范
public interface Data<E> { void add(E e);E get();
}// 实现接口时指定类型(如E为Student)
public class StudentData implements Data<Student> {@Override public void add(Student student) { ... }@Override public Student get() { ... }
}
三、泛型方法(含类型变量的方法)
修饰符 <T> 返回值类型 方法名(T param) { ... },适配多类型参数。
// 泛型方法:可打印任意类型的数组
public static <T> void printArray(T[] array) {for (T t : array) { System.out.print(t + " ");}
}// 使用:自动识别类型
Integer[] nums = {1,2,3};
printArray(nums); // 打印1 2 3
String[] strs = {"a","b"};
printArray(strs); // 打印a b
2. 泛型通配符与上下限
| 通配符形式 | 说明 | 示例 |
|---|---|---|
| ? (无限制) | 可接收任意类型 | public void show(List<?> list) { … } |
| ? extends 类型 | 上限:仅接收"类型及其子类" | List<? extends Car> 可接收 List 、 List |
| ? super 类型 | 下限:仅接收"类型及其父类" | List<? super Car> 可接收 List 、 List |
注意:
- 泛型擦除:泛型仅工作在编译阶段,编译为class 文件后,泛型信息被擦除(如ArrayList< String > 擦除为ArrayList );
- 不支持基本类型:泛型仅接收引用类型(如ArrayList< Integer> 而非ArrayList< int> ),需用包装类替代;
- 静态成员不能使用泛型类的类型变量(静态成员属于类,泛型类型随对象确定)。
(七) 常用API(java.lang包核心)
1. Object类(所有类的祖宗类)
所有类默认继承Object,其方法可被所有对象直接调用,核心方法如下:
| 方法名 | 说明 |
|---|---|
| public String toString() | 返回对象的字符串表示(默认格式:类名 @ 哈希码 ),需子类重写以返回具体内容(如 Student{name=" 张三 "} ) |
| public boolean equals(Object o) | 默认比较对象地址(同 == ),需子类重写以比较内容(如 比较学生的学号和姓名) |
| protected Object clone() | 复制对象并返回新对象,需类实现 Cloneable 接口(否则 抛异常),分浅克隆和深克隆 |
2. 克隆的两种方式
| 类型 | 特点 |
|---|---|
| 浅克隆 | 基本类型直接拷贝,引用类型仅拷贝地址(新对象与原对象共享引用数据) |
| 深克隆 | 基本类型直接拷贝,引用类型创建新对象(新对象与原对象的引用数据完全独立) |
3. Objects工具类
java.util.Objects是静态工具类,提供安全的对象操作方法,避免空指针异常:
| 方法名 | 说明 |
|---|---|
| public static boolean equals(Object a, Object b) | 先判断 a 是否为 null , 再调用 a.equals(b) ,安全比较对象内容 |
| public static boolean isNull(Object obj) | 判断对象是否为 null (为 null 返回 true ) |
| public static boolean nonNull(Object obj) | 判断对象是否不为 null (不为 null 返回 true ) |
4. 包装类(基本类型→对象)
为解决"泛型/集合不支持基本类型"问题,将8种基本类型封装为引用类型(包装类)。
| 基本类型 | 包装类 | 基本类型 | 包装类 |
|---|---|---|---|
| byte | Byte | float | Float |
| short | Short | double | Double |
| int | Integer | char | Character |
| long | Long | boolean | Boolean |
-
自动装箱/拆箱(JDK5+):
- 装箱:基本类型→包装类(如int a = 10; Integer b = a;);
- 拆箱:包装类→基本类型(如Integer b = 10; int a = b;)。
-
常用操作:
- 基本类型→字符串:Integer.toString(123) → “123”;
- 字符串→基本类型:Integer.parseInt(“123”) → 123(或Integer.valueOf(“123”))。
5. StringBuilder(可变字符串)
- String是不可变字符串(修改时生成新对象),
- StringBuilder是可变字符串容器,修改效率更高,适合频繁拼接/修改字符串。
| 构造器 | 说明 |
|---|---|
| public StringBuilder() | 创建空白可变字符串(初始容量16) |
| public StringBuilder(String str) | 创建含指定字符串的可变对象 |
| 方法名 | 说明 |
|---|---|
| public StringBuilder append(任意类型) | 添加数据并返回自身(支持链式调用) |
| public StringBuilder reverse() | 反转字符串内容 |
| public int length() | 返回字符串长度 |
| public String toString() | 转为 String 类型 |
注意::
- StringBuffer 与StringBuilder 用法一致
- StringBuffer 是线程安全的(效率低)
- StringBuilder 线程不安全(效率高,推荐单线程使用)
6. StringJoiner(JDK8+,简化拼接)
- StringJoiner是 StringBuilder 的增强工具
- 专为"分隔符拼接"设计,代码更简洁(如拼接数组为[11,22,33])
| 构造器 | 说明 |
|---|---|
| public StringJoiner(CharSequence delimiter) | 指定间隔符(如 , ) |
| public StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) | 指定间隔符、前缀(如 [ )、后缀(如 ] ) |
| 方法名 | 说明 |
|---|---|
| public StringJoiner add(CharSequence str) | 添加内容并返回自身 |
| public int length() | 返回拼接后字符串长度 |
| public String toString() | 返回拼接结果( String 类型) |
示例:
import java.util.StringJoiner;
public class Test { public static void main(String[] args) {int[] arr = {11,22,33}; StringJoiner sj = new StringJoiner(",", "[", "]"); // 间隔符, 前缀[, 后缀]for (int num : arr) { sj.add(String.valueOf(num));}System.out.println(sj); // 输出[11,22,33]}
}
(八) 基础工具类
1. Math(数学工具类)
全静态方法,用于常见数学运算,无需创建对象。
| 方法名 | 说明 |
|---|---|
| abs(int/double a) | 获取绝对值(结果非负) |
| ceil(double a) | 向上取整(返回不小于a的最小整数) |
| floor(double a) | 向下取整(返回不大于a的最大整数) |
| round(float/double a) | 四舍五入(返回long/int) |
| max(int a, int b) | 获取两数最大值(min为最小值) |
| pow(double a, double b) | 计算a的b次幂 |
| random() | 生成[0.0,1.0)的随机double值 |
2. System(系统工具类)
代表当前Java程序所在系统,提供系统级操作。
| 方法名 | 说明 | 应用场景 |
|---|---|---|
| exit(int status) | 终止Java虚拟机(0为正常退出,非0异常) | 手动结束程序 |
| currentTimeMillis() | 返回当前系统时间毫秒值(1970-01-01起) | 程序性能分析(计算执行耗时) |
示例:性能分析
long start = System.currentTimeMillis();
// 执行耗时操作(如循环)
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) / 1000.0 + "s");
3. Runtime(运行环境类)
代表程序运行环境,单例类(仅一个实例),通过Runtime.getRuntime()获取实例。
| 方法名 | 说明 |
|---|---|
| getRuntime() | 获取当前Java应用的Runtime实例 |
| availableProcessors() | 返回虚拟机可用处理器数(如8核返回8) |
| totalMemory() / freeMemory() | 返回虚拟机总内存/可用内存(字节) |
| exec(String command) | 启动外部程序(如 exec(“notepad.exe”) 打开记事本) |
(九) BigDecimal(高精度小数)
解决浮点型运算(如0.1+0.2=0.30000000000000004)的精度失真问题。
构造器选择:
- BigDecimal.valueOf(double val)(内部转为 String,避免失真)
- new BigDecimal(String val)(直接传入字符串,如new BigDecimal(“0.1”))
| 方法名 | 说明 |
|---|---|
| add(BigDecimal b) | 加法 |
| subtract(BigDecimal b) | 减法 |
| multiply(BigDecimal b) | 乘法 |
| divide(BigDecimal b, int scale, RoundingMode mode) | 除法(指定精度和舍入模式) |
| doubleValue() | 转为double类型 (最终需返回基本类型时用) |
示例:
BigDecimal a = BigDecimal.valueOf(0.1);
BigDecimal b = BigDecimal.valueOf(0.2);
BigDecimal sum = a.add(b); // 0.3
System.out.println(sum.doubleValue()); // 输出0.3
(十) 日期与时间API(JDK8+)
特点:不可变对象(修改返回新对象)、线程安全、支持纳秒精度。
| 类名 | 功能 | 核心操作 |
|---|---|---|
| LocalDate/LocalTime | 仅年月日/仅时分秒 | now()(当前)、 of()(指定)、 plus/minus (增减) |
| LocalDateTime | 年月日+时分秒 | 支持格式化( format )、解析 ( parse )、字段修改 |
| ZonedDateTime | 带时区时间(如Asia/Shanghai) | now(ZoneId.of(“Asia/Shanghai”)) 获指定时区时间 |
| Instant | 时间戳(替代Date) | now()(当前标准时间) |
| DateTimeFormatter | 格式化/解析(替代 SimpleDateFormat) | ofPattern(“yyyy-MM-dd HH:mm:ss”) |
| Period/Duration | 时间间隔计算 | Period.between (LocalDate间隔,年月日)、 Duration.between (时间间隔,时分秒纳秒) |
| 操作类型 | 方法示例 | 说明 |
|---|---|---|
| 获取字段 | ldt.getYear() 、 ldt.getHour() | 获取年、小时等 |
| 修改字段 | ldt.withYear(2025) | 修改年为2025,返回新对象 |
| 增减时间 | ldt.plusDays(3) 、 ldt.minusHours(2) | 加3天、减2小时,返回新对象 |
| 比较 | ldt1.isBefore(ldt2) | 判断ldt1是否在ldt2之前 |
| 格式化 | ldt.format(formatter) | 转为指定格式字符串 |
| 解析 | LocalDateTime.parse(“2024-05-20 14:30:00”, formatter) | 字符串转LocalDateTime |
| 类名 | 功能 | 核心方法 |
|---|---|---|
| Period | 计算两个LocalDate的间隔(年月日) | Period.between(startDate, endDate) → 获取年差、月差、日差 |
| Duration | 计算时间间隔(时分秒纳秒) | Duration.between(startTime, endTime) → 转为天、小时、秒等 |
(十一) Arrays(数组工具类)
全静态方法,用于数组的常用操作(遍历、拷贝、排序等)
| 方法名 | 说明 |
|---|---|
| toString( 类型 [ ] arr) | 将数组转为字符串 (如 [1,2,3] ) |
| copyOf( 类型 [ ] arr, int newLen) | 拷贝数组,指定新长度 |
| copyOfRange( 类型 [ ] arr, int from, int to) | 拷贝指定范围(包前不包后) |
| sort( 类型 [ ] arr) | 数组排序(默认升序,基本类型) |
| sort(T[ ] arr, Comparator<? super T> c) | 对象数组自定义排序 |
(十二) Lambda表达式(简化匿名内部类)
前提:仅简化函数式接口(仅1个抽象方法,注@FunctionalInterface);
语法: (抽象方法形参列表) -> { 抽象方法体代码 }
省略规则(进一步简化):
- 形参类型可省略;
- 若仅一个形参,() 可省略;
- 若方法体仅1行代码,{} 和; 可省略,若为return 语句,return 也需省略。
示例:
// 匿名内部类
Arrays.sort(students, new Comparator<Student>() { @Overridepublic int compare(Student s1, Student s2) { return s1.getAge() - s2.getAge();}
});// Lambda简化(省略类型、大括号、return)
Arrays.sort(students, (s1, s2) -> s1.getAge() - s2.getAge());
当Lambda体仅调用一个方法,且参数传递一致时,可用方法引用替代。
| 引用类型 | 格式 | 示例 |
|---|---|---|
| 静态方法引用 | 类名 :: 静态方法名 | Math::abs (替代 (x)->Math.abs(x) ) |
| 实例方法引用 | 对象名 :: 实例方法名 | str::length (替代 ()->str.length() ) |
| 特定类型方法引用 | 类型 :: 实例方法名 | String::compareTo (替代 (s1,s2)->s1.compareTo(s2) ) |
| 构造器引用 | 类名 ::new | Student::new (替代 (name,age)->new Student(name,age) ) |
(十三) 异常(程序错误处理)
异常是程序编译或运行时出现的错误(如除以0、数组索引越界),Java将其封装为对象(继承 Throwable)。
一、异常体系(核心层级)
Throwable(顶层)
├─ Error(系统级错误,无需处理):如内存溢出、虚拟机错误,程序员无需关注
└─ Exception(程序级异常,需处理) ├─ 运行时异常(RuntimeException子类):编译不报错,运行时可能出现 │ ├─ ArrayIndexOutOfBoundsException(数组索引越界) │ ├─ ArithmeticException(算术异常,如除以0)│ └─ NullPointerException(空指针异常)└─ 编译时异常(非RuntimeException子类):编译阶段报错,必须处理├─ ParseException(日期解析异常)└─ IOException(IO异常)
二、异常的处理方式
- 抛出(throws):
方法上声明异常,抛给调用者处理,自身不处理。
public void 方法名() throws 异常1, 异常2 {...}
- 捕获异常(try-catch):
监控异常代码,捕获后自行处理。
try { // 可能出现异常的代码(监控区)
} catch (异常类型1 变量名) { // 异常1的处理逻辑(如打印日志)
} catch (异常类型2 变量名) { // 异常2的处理逻辑
} catch (Exception e) { // 推荐:用Exception捕获所有异常(兜底)e.printStackTrace(); // 打印异常堆栈(查bug关键)
}
三、自定义异常
- 运行时异常:
继承RuntimeException,重写构造器,用throw new 自定义异常(消息)抛出。(编译不报错);
// 自定义运行时异常:年龄不合法
public class AgeIllegalException extends RuntimeException {// 无参构造器public AgeIllegalException() {}// 带消息的构造器public AgeIllegalException(String message) {super(message);}
}// 使用
public static void checkAge(int age) {if (age < 18 || age > 60) {throw new AgeIllegalException("年龄必须18-60岁"); // 抛出异常}
}
- 编译时异常:
继承Exception,重写构造器,用 throw new 自定义异常(消息) 抛出,且方法需用 throws 声明。(编译报错,提醒强)。
// 自定义编译时异常:年龄不合法
public class AgeIllegalException extends Exception {public AgeIllegalException() {}public AgeIllegalException(String message) {super(message);}
}// 使用:方法需声明抛出
public static void checkAge(int age) throws AgeIllegalException {if (age < 18 || age > 60) {throw new AgeIllegalException("年龄必须18-60岁");}
}
四、异常的核心作用
- 定位bug:异常堆栈( printStackTrace() )提供错误代码行和原因,是查bug的关键;
- 传递执行状态:作为方法的"特殊返回值",通知上层调用者底层执行失败(如"年龄不合法")。
(十四) File类(文件/文件夹操作)
- 核心定位:操作文件/文件夹本身(创建、删除、获取信息),不能读写文件内容。
- 路径分类:
- 绝对路径(盘符开头,如 D:/test.txt )
- 相对路径(无盘符,默认当前工程/模块下)
| 构造器 | 说明 |
|---|---|
| File(String pathname) | 根据文件路径创建对象(路径可存在/不存在) |
| File(String parent, String child) | 父路径+子路径创建对象 |
| File(File parent, String child) | 父路径File对象+子路径创建对象 |
| 方法名 | 说明 |
|---|---|
| exists() | 判断路径是否存在(存在返回 true ) |
| isFile() | 判断是否为文件(是返回 true ) |
| isDirectory() | 判断是否为文件夹(是返回 true ) |
| getName() | 获取文件/文件夹名称(含后缀) |
| length() | 获取文件大小(字节数,文件夹返回0) |
| lastModified() | 获取最后修改时间(毫秒值,1970年起) |
| getAbsolutePath() | 获取绝对路径 |
| 方法名 | 说明 | 注意事项 |
|---|---|---|
| createNewFile () | 创建空文件(成功返回 true ) | 需处理 IOException ,路径不存在会报错 |
| mkdir() | 创建一级文件夹 | 父文件夹不存在则创建失败 |
| mkdirs() | 创建多级文件夹(推荐) | 父文件夹不存在会自动创建 |
| delete() | 删除文件/空文件夹(成功返回 true ) | 非空文件夹无法直接删除,删除后不进回收站 |
| 方法名 | 说明 | 注意事项 |
|---|---|---|
| list() | 返回文件夹下一级文件/文件夹名称数组 | 主调是文件或路径不存在时返回 null |
| listFiles() | 返回文件夹下一级文件/文件夹的 File数组 | 空文件夹返回长度为0的数组,无权限访问返回 null |
