【第七章】Java------String类与常用工具类
- 一、为什么要学习这些常用工具类
- [二、String 类概述](#二、String 类概述)
-
- [1. 什么是 String](#1. 什么是 String)
- [2. 为什么 String 这么特殊](#2. 为什么 String 这么特殊)
- [3. String 的重要地位](#3. String 的重要地位)
- [三、String 的创建方式](#三、String 的创建方式)
-
- [1. 直接赋值](#1. 直接赋值)
- [2. 使用构造方法](#2. 使用构造方法)
- [3. 两种写法的区别](#3. 两种写法的区别)
-
- 直接赋值
- [`new String(...)`](#
new String(...))
- 四、字符串常量池
-
- [1. 什么是字符串常量池](#1. 什么是字符串常量池)
- [2. 为什么需要常量池](#2. 为什么需要常量池)
- [3. 示例](#3. 示例)
- [4. 再看 `new String`](#4. 再看
new String)
- [五、String 的不可变性](#五、String 的不可变性)
-
- [1. 什么叫不可变](#1. 什么叫不可变)
- [2. 为什么 String 设计成不可变](#2. 为什么 String 设计成不可变)
- [3. 不可变性带来的直观现象](#3. 不可变性带来的直观现象)
- 六、字符串比较
-
- [1. `==` 比较的是什么](#1.
==比较的是什么) - [2. 比较字符串内容应该用 `equals`](#2. 比较字符串内容应该用
equals) - [3. `equalsIgnoreCase`](#3.
equalsIgnoreCase) - [4. 开发中的常见错误](#4. 开发中的常见错误)
- [1. `==` 比较的是什么](#1.
- [七、String 的常用方法](#七、String 的常用方法)
-
- [1. 获取长度:`length()`](#1. 获取长度:
length()) - [2. 判断是否为空字符串:`isEmpty()`](#2. 判断是否为空字符串:
isEmpty()) - [3. 获取指定位置字符:`charAt(int index)`](#3. 获取指定位置字符:
charAt(int index)) - [4. 拼接字符串:`concat()`](#4. 拼接字符串:
concat()) - [5. 字符串包含:`contains()`](#5. 字符串包含:
contains()) - [6. 查找位置:`indexOf()`](#6. 查找位置:
indexOf()) - [7. 最后一次出现的位置:`lastIndexOf()`](#7. 最后一次出现的位置:
lastIndexOf()) - [8. 截取子串:`substring()`](#8. 截取子串:
substring()) - [9. 替换:`replace()`](#9. 替换:
replace()) - [10. 转大小写](#10. 转大小写)
- [11. 去除首尾空格:`trim()`](#11. 去除首尾空格:
trim()) - [12. 分割字符串:`split()`](#12. 分割字符串:
split()) - [13. 判断前缀和后缀](#13. 判断前缀和后缀)
- [14. 转字符数组:`toCharArray()`](#14. 转字符数组:
toCharArray()) - [15. 静态方法 `valueOf()`](#15. 静态方法
valueOf())
- [1. 获取长度:`length()`](#1. 获取长度:
- [八、String 在刷题和开发中的常见场景](#八、String 在刷题和开发中的常见场景)
-
- [1. 遍历字符串](#1. 遍历字符串)
- [2. 字符串转数字](#2. 字符串转数字)
- [3. 数字转字符串](#3. 数字转字符串)
- [4. 判断回文、统计字符、分割路径](#4. 判断回文、统计字符、分割路径)
- [九、BigInteger 类](#九、BigInteger 类)
-
- [1. 为什么需要 BigInteger](#1. 为什么需要 BigInteger)
- [2. BigInteger 的特点](#2. BigInteger 的特点)
- [3. 创建方式](#3. 创建方式)
- [4. 常用方法](#4. 常用方法)
- [5. 注意事项](#5. 注意事项)
- [十、BigDecimal 类](#十、BigDecimal 类)
-
- [1. 为什么不能直接用 float 和 double 处理精确小数](#1. 为什么不能直接用 float 和 double 处理精确小数)
- [2. BigDecimal 的作用](#2. BigDecimal 的作用)
- [3. 创建方式](#3. 创建方式)
- [4. 常用方法](#4. 常用方法)
- [5. 比较大小](#5. 比较大小)
- [6. `equals()` 的一个细节](#6.
equals()的一个细节)
- [十一、BigInteger 与 BigDecimal 的区别](#十一、BigInteger 与 BigDecimal 的区别)
- [十二、Date 类](#十二、Date 类)
-
- [1. Date 类的作用](#1. Date 类的作用)
- [2. 常见创建方式](#2. 常见创建方式)
- [3. 获取时间戳](#3. 获取时间戳)
- [4. 设置时间](#4. 设置时间)
- [5. Date 类的局限](#5. Date 类的局限)
- [十三、Calendar 类](#十三、Calendar 类)
-
- [1. Calendar 的作用](#1. Calendar 的作用)
- [2. 创建方式](#2. 创建方式)
- [3. 获取常见字段](#3. 获取常见字段)
- [4. 注意月份从 0 开始](#4. 注意月份从 0 开始)
- [5. 修改日期](#5. 修改日期)
- [6. 日期加减](#6. 日期加减)
- [7. 转为 Date 对象](#7. 转为 Date 对象)
- [十四、Date 与 Calendar 的关系](#十四、Date 与 Calendar 的关系)
-
- [1. Date 更像"时间点"](#1. Date 更像“时间点”)
- [2. Calendar 更像"时间工具箱"](#2. Calendar 更像“时间工具箱”)
- [3. 学习阶段怎么理解](#3. 学习阶段怎么理解)
- [十五、System 类](#十五、System 类)
-
- [1. System 是什么](#1. System 是什么)
- [2. `System.out.println`](#2.
System.out.println) - [3. `currentTimeMillis()`](#3.
currentTimeMillis()) - [4. `exit()`](#4.
exit()) - [5. `arraycopy()`](#5.
arraycopy()) - [6. `getProperty()`](#6.
getProperty())
- [十六、Runtime 类](#十六、Runtime 类)
- [十七、Math 类](#十七、Math 类)
-
- [1. Math 是什么](#1. Math 是什么)
- [2. 常用方法](#2. 常用方法)
- [3. Math 的特点](#3. Math 的特点)
- 十八、这些类在实际开发中的典型使用场景
-
- [1. String](#1. String)
- [2. BigInteger](#2. BigInteger)
- [3. BigDecimal](#3. BigDecimal)
- [4. Date / Calendar](#4. Date / Calendar)
- [5. System](#5. System)
- [6. Runtime](#6. Runtime)
- [7. Math](#7. Math)
- 十九、学习这些工具类时最容易犯的错误
-
- [1. 用 `==` 比较字符串内容](#1. 用
==比较字符串内容) - [2. 忘记 String、BigInteger、BigDecimal 的不可变性](#2. 忘记 String、BigInteger、BigDecimal 的不可变性)
- [3. 用 `double` 做金额运算](#3. 用
double做金额运算) - [4. 使用 `new BigDecimal(0.1)`](#4. 使用
new BigDecimal(0.1)) - [5. 忘记 `Calendar.MONTH` 从 0 开始](#5. 忘记
Calendar.MONTH从 0 开始) - [6. 把 `Math.random()` 当成整数随机数](#6. 把
Math.random()当成整数随机数) - [7. 混淆 `Date` 和 `Calendar`](#7. 混淆
Date和Calendar)
- [1. 用 `==` 比较字符串内容](#1. 用
- 二十、这些类之间的联系与区别
-
- [1. String 和其他类](#1. String 和其他类)
- [2. BigInteger 和 BigDecimal](#2. BigInteger 和 BigDecimal)
- [3. Date 和 Calendar](#3. Date 和 Calendar)
- [4. System、Runtime、Math](#4. System、Runtime、Math)
- 二十一、学习建议
-
- [1. 先学"用途",再背方法](#1. 先学“用途”,再背方法)
- [2. 重点掌握高频方法](#2. 重点掌握高频方法)
- [3. 通过小例子反复练](#3. 通过小例子反复练)
- 二十二、本章知识总结
-
- [1. String 类](#1. String 类)
- [2. BigInteger](#2. BigInteger)
- [3. BigDecimal](#3. BigDecimal)
- [4. Date 与 Calendar](#4. Date 与 Calendar)
- [5. System](#5. System)
- [6. Runtime](#6. Runtime)
- [7. Math](#7. Math)
- 二十三、结语
- 二十四、附:常见语法速查表
-
- [1. String](#1. String)
- [2. BigInteger](#2. BigInteger)
- [3. BigDecimal](#3. BigDecimal)
- [4. Date](#4. Date)
- [5. Calendar](#5. Calendar)
- [6. System](#6. System)
- [7. Runtime](#7. Runtime)
- [8. Math](#8. Math)
前言
在学习 Java 的过程中,很多同学会把注意力主要放在:
- 基本语法
- 面向对象
- 数组
- 方法
- 异常
- 集合
这些内容上。
但真正开始写程序以后,很快就会发现,除了语法和面向对象思想之外,Java 中还提供了大量非常常用、非常实用的工具类。
这些类虽然不一定像"继承、多态、异常"那样抽象,但在实际开发和刷题中出现的频率却非常高。
例如:
- 处理字符串时,离不开
String - 处理高精度整数时,离不开
BigInteger - 处理精确小数时,离不开
BigDecimal - 处理时间时,经常会接触
Date和Calendar - 获取系统时间、复制数组、退出程序时,常会用到
System - 了解当前运行环境、执行外部命令时,会遇到
Runtime - 做数学运算时,常会使用
Math
这些类之所以重要,是因为它们几乎覆盖了日常编程中最常见的几类需求:
- 字符串处理
- 高精度数值运算
- 日期时间处理
- 系统操作
- 数学计算
如果对这些类不了解,就会经常出现下面这些情况:
- 不知道为什么字符串明明"改了",结果原变量没变
- 不知道为什么
0.1 + 0.2算出来不是严格的0.3 - 不知道大整数为什么不能直接用
int或long - 不知道时间类之间的关系
- 不知道
System.currentTimeMillis()是干什么的 - 不知道
Math.random()、Math.abs()、Math.max()应该怎么用
因此,这一章的学习重点不只是"会调用方法",更重要的是理解这些类分别解决什么问题、适合用在什么场景、使用时有哪些细节要注意。
本章将围绕 Java 中最常见的几个工具类展开说明,重点讲解:
StringBigIntegerBigDecimalDateCalendarSystemRuntimeMath
说明一下:你问题里写的是 data类 和 canlendar类,这里按 Java 中实际常见写法统一讲解为:
Date类Calendar类
通过本章学习,可以掌握:
String的本质与常用方法- 字符串为什么具有不可变性
- 字符串常量池的基本思想
BigInteger和BigDecimal的作用与常用方法- 为什么浮点数运算不能直接用于高精度场景
Date和Calendar的基本使用方法System、Runtime、Math常见方法与应用场景- 这些工具类在刷题和开发中的典型用途
一、为什么要学习这些常用工具类
1. 它们出现得非常频繁
Java 中有很多类,但并不是所有类在初学阶段都同样重要。
有些类可能很专业、很细分,而有些类几乎每天写代码都会用到。
比如:
- 判断字符串长度要用
String.length() - 比较字符串内容要用
equals() - 金额运算常常要用
BigDecimal - 处理大整数常用
BigInteger - 获取当前时间常用
Date或System.currentTimeMillis() - 取绝对值、最大值、随机数要用
Math
所以学习这些类,不是"扩展知识",而是"编程必备"。
2. 它们解决的都是实际问题
这些类之所以被设计出来,不是为了增加语法复杂度,而是因为普通基本类型和普通语法解决不了某些现实问题。
例如:
字符串不是普通数组
字符串既要方便比较,又要方便截取、查找、拼接,因此需要专门的 String 类。
金额计算不能随便用 double
因为 double 是二进制浮点数,很多十进制小数无法精确表示,所以需要 BigDecimal。
超大整数会超出 long
比如非常大的数字运算,就需要 BigInteger。
时间信息很复杂
年月日、时分秒、星期、毫秒这些信息组合在一起,仅靠基本类型很难优雅处理,因此有 Date、Calendar 这样的类。
3. 它们帮助你少造轮子
如果没有这些工具类,很多功能都要自己手写:
- 字符串查找
- 字符串切割
- 高精度加减乘除
- 日期格式转换
- 获取系统信息
- 数学运算
而 Java 已经帮我们准备好了这些功能,学习这些类,其实就是学习"如何高效使用 Java 提供的现成能力"。
二、String 类概述
1. 什么是 String
String 是 Java 中专门用来表示字符串的类。所谓字符串,本质上就是一串字符组成的内容,例如:
"hello""Java""123456""张三"
在 Java 中,字符串不是基本数据类型,而是一个类。
例如:
java
String s = "hello";
这里的 s 不是一个普通变量,而是一个 String 类型的引用。
2. 为什么 String 这么特殊
String 虽然本质是类,但在使用上又比普通类更方便。
例如:
java
String s = "abc";
这种写法看起来像基本类型赋值,但实际上底层仍然是对象。
之所以这样设计,是因为字符串在编程中太常用了。
Java 为了提高可读性和使用便利性,对 String 做了很多特殊优化。
3. String 的重要地位
在 Java 中,String 几乎无处不在:
- 输出文字信息
- 用户输入
- 文件路径
- 网络请求参数
- JSON 数据
- SQL 语句
- 日志信息
所以 String 是必须熟练掌握的核心类之一。
三、String 的创建方式
1. 直接赋值
java
String s1 = "hello";
这是最常见的写法。
2. 使用构造方法
java
String s2 = new String("hello");
或者:
java
char[] arr = {'h', 'e', 'l', 'l', 'o'};
String s3 = new String(arr);
3. 两种写法的区别
表面上看,它们都能得到字符串 "hello",但底层创建对象的方式不同。
直接赋值
java
String s1 = "hello";
会优先考虑字符串常量池。
new String(...)
java
String s2 = new String("hello");
通常会在堆中再创建新的字符串对象。
因此在面试和笔试中,经常会考字符串对象个数问题。
四、字符串常量池
1. 什么是字符串常量池
Java 为了提高字符串复用率,对字符串做了优化。对于字面量字符串,例如 "abc",JVM 通常会把它放进一个专门的区域中,这个区域通常被称为:
- 字符串常量池
2. 为什么需要常量池
因为字符串使用频率太高。
如果每写一次 "hello" 都新建一个对象,会浪费很多内存。
所以常量池的思想是:
相同的字符串字面量尽量复用。
3. 示例
java
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
输出通常是:
text
true
原因不是说字符串内容比较,而是:
s1和s2指向了常量池中的同一个对象
4. 再看 new String
java
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s1 == s2);
输出通常是:
text
false
因为:
s1指向常量池对象s2指向堆中的新对象
内容一样,但地址不同。
五、String 的不可变性
1. 什么叫不可变
String 最重要的一个特性,就是:
字符串对象一旦创建,其内容不能再被改变。
这就叫字符串的不可变性。
例如:
java
String s = "abc";
s = s + "def";
很多初学者会误以为:
- 原来的字符串
"abc"被直接改成了"abcdef"
其实不是。
真正发生的是:
- 原来的
"abc"仍然存在 - 新产生了一个
"abcdef"字符串对象 s重新指向这个新对象
2. 为什么 String 设计成不可变
不可变性的好处有很多:
- 更安全
- 更适合放入常量池复用
- 更适合作为哈希结构的键
- 多线程环境下更稳定
3. 不可变性带来的直观现象
例如:
java
String s = "hello";
s.toUpperCase();
System.out.println(s);
输出仍然是:
text
hello
因为 toUpperCase() 返回的是新字符串,原字符串本身没有被改。
如果要接收结果,应该写成:
java
s = s.toUpperCase();
六、字符串比较
1. == 比较的是什么
在 Java 中,== 如果用于引用类型,比较的是:
两个引用是否指向同一个对象。
例如:
java
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
2. 比较字符串内容应该用 equals
java
System.out.println(s1.equals(s3)); // true
这是因为 equals() 比较的是字符串内容。
3. equalsIgnoreCase
如果想忽略大小写比较,可以使用:
java
String s1 = "Hello";
String s2 = "hello";
System.out.println(s1.equalsIgnoreCase(s2)); // true
4. 开发中的常见错误
错误写法:
java
if (s1 == s2) {
}
这在字符串内容比较中经常是错的。
一般应优先使用:
java
if (s1.equals(s2)) {
}
如果担心空指针,更稳妥的方式是:
java
if ("abc".equals(s1)) {
}
这样即使 s1 是 null,也不会报错。
七、String 的常用方法
这一部分非常重要。
1. 获取长度:length()
java
String s = "hello";
System.out.println(s.length()); // 5
2. 判断是否为空字符串:isEmpty()
java
String s = "";
System.out.println(s.isEmpty()); // true
注意:
- 空字符串
""和null不是一回事
3. 获取指定位置字符:charAt(int index)
java
String s = "hello";
System.out.println(s.charAt(1)); // e
4. 拼接字符串:concat()
java
String s1 = "hello";
String s2 = s1.concat(" world");
System.out.println(s2);
不过平时更常用的是 + 拼接。
5. 字符串包含:contains()
java
String s = "hello world";
System.out.println(s.contains("world")); // true
6. 查找位置:indexOf()
java
String s = "hello";
System.out.println(s.indexOf("l")); // 2
如果找不到,返回:
text
-1
7. 最后一次出现的位置:lastIndexOf()
java
String s = "abca";
System.out.println(s.lastIndexOf("a")); // 3
8. 截取子串:substring()
java
String s = "hello";
System.out.println(s.substring(1)); // ello
System.out.println(s.substring(1, 4)); // ell
注意:
- 起始下标包含
- 结束下标不包含
9. 替换:replace()
java
String s = "hello";
System.out.println(s.replace("l", "x")); // hexxo
10. 转大小写
java
String s = "Hello";
System.out.println(s.toUpperCase()); // HELLO
System.out.println(s.toLowerCase()); // hello
11. 去除首尾空格:trim()
java
String s = " hello ";
System.out.println(s.trim()); // hello
12. 分割字符串:split()
java
String s = "java,python,c";
String[] arr = s.split(",");
13. 判断前缀和后缀
java
String s = "hello.java";
System.out.println(s.startsWith("he")); // true
System.out.println(s.endsWith(".java")); // true
14. 转字符数组:toCharArray()
java
String s = "abc";
char[] arr = s.toCharArray();
15. 静态方法 valueOf()
可以把其他类型转换成字符串:
java
String s1 = String.valueOf(123);
String s2 = String.valueOf(true);
八、String 在刷题和开发中的常见场景
1. 遍历字符串
java
String s = "hello";
for (int i = 0; i < s.length(); i++) {
System.out.println(s.charAt(i));
}
2. 字符串转数字
java
String s = "123";
int num = Integer.parseInt(s);
3. 数字转字符串
java
int num = 123;
String s = String.valueOf(num);
4. 判断回文、统计字符、分割路径
这些都离不开 String 的基本方法。
九、BigInteger 类
1. 为什么需要 BigInteger
Java 中整数类型有:
byteshortintlong
它们都属于定长整数。
也就是说,它们能表示的数据范围是有限的。
例如:
int大约是 21 亿范围long虽然更大,但仍然有限
如果要处理超大整数,例如:
- 非常大的数学运算
- 高精度整数计算
- 大整数乘法
这时 int 和 long 都不够用,就需要:
BigInteger
2. BigInteger 的特点
BigInteger 表示任意精度的整数。
也就是说,只要内存允许,它可以表示非常大的整数。
3. 创建方式
通常用字符串创建:
java
import java.math.BigInteger;
BigInteger num = new BigInteger("123456789123456789123456789");
为什么不用普通数字字面量?
因为普通字面量本身就可能超出基本类型范围,编译阶段就会出问题。
4. 常用方法
加法:add()
java
BigInteger a = new BigInteger("100");
BigInteger b = new BigInteger("200");
System.out.println(a.add(b)); // 300
减法:subtract()
java
System.out.println(b.subtract(a)); // 100
乘法:multiply()
java
System.out.println(a.multiply(b)); // 20000
除法:divide()
java
BigInteger x = new BigInteger("10");
BigInteger y = new BigInteger("3");
System.out.println(x.divide(y)); // 3
取余:remainder()
java
System.out.println(x.remainder(y)); // 1
比较大小:compareTo()
java
System.out.println(a.compareTo(b)); // -1
System.out.println(b.compareTo(a)); // 1
System.out.println(a.compareTo(a)); // 0
比较规则:
- 大于返回正数
- 小于返回负数
- 等于返回
0
5. 注意事项
BigInteger 和 String 类似,也是不可变对象。
调用方法后会返回新对象,不会直接修改原对象。
例如:
java
BigInteger a = new BigInteger("10");
a.add(new BigInteger("5"));
System.out.println(a); // 还是 10
如果要保存结果,应写:
java
a = a.add(new BigInteger("5"));
十、BigDecimal 类
1. 为什么不能直接用 float 和 double 处理精确小数
这是 Java 初学者很容易忽略,但非常重要的一点。
例如:
java
System.out.println(0.1 + 0.2);
很多人以为结果是:
text
0.3
但实际可能是:
text
0.30000000000000004
原因不是 Java 算错了,而是:
浮点数在计算机内部采用二进制近似表示,很多十进制小数无法被精确表示。
所以在下面这些场景中,不能随便用 double:
- 金额运算
- 精确小数比较
- 财务系统
- 结算系统
这时候应该使用:
BigDecimal
2. BigDecimal 的作用
BigDecimal 用于表示高精度小数,可以避免普通浮点数精度丢失的问题。
3. 创建方式
推荐使用字符串创建:
java
import java.math.BigDecimal;
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
不推荐直接写:
java
BigDecimal a = new BigDecimal(0.1);
原因是:
0.1本身作为double已经不精确了- 再拿它构造
BigDecimal,误差已经带进来了
4. 常用方法
加法:add()
java
System.out.println(a.add(b)); // 0.3
减法:subtract()
java
System.out.println(b.subtract(a)); // 0.1
乘法:multiply()
java
System.out.println(a.multiply(b)); // 0.02
除法:divide()
java
BigDecimal x = new BigDecimal("1");
BigDecimal y = new BigDecimal("3");
System.out.println(x.divide(y, 2, BigDecimal.ROUND_HALF_UP));
这里表示:
- 保留 2 位小数
- 采用四舍五入方式
注意:如果是无法除尽的小数,直接 divide() 可能抛异常,因此常常要指定:
- 保留位数
- 舍入方式
5. 比较大小
不要用 ==,也不要随意只看 equals()。
更常用的是:
java
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1.00");
System.out.println(a.compareTo(b)); // 0
compareTo() 更适合比较数值大小。
6. equals() 的一个细节
java
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1.00");
System.out.println(a.equals(b)); // false
因为 equals() 不仅比较值,还比较精度形式。
所以开发中比较金额是否相等,通常更推荐:
java
a.compareTo(b) == 0
十一、BigInteger 与 BigDecimal 的区别
1. BigInteger
- 只能表示整数
- 用于超大整数
2. BigDecimal
- 可以表示小数
- 用于高精度十进制运算
3. 如何选择
只处理超大整数
用 BigInteger
处理金额、精确小数
用 BigDecimal
十二、Date 类
1. Date 类的作用
Date 类用于表示日期和时间信息。
可以简单理解为:
Date对象通常表示一个具体的时间点。
2. 常见创建方式
java
import java.util.Date;
Date d1 = new Date();
System.out.println(d1);
表示当前系统时间。
也可以根据毫秒值创建:
java
Date d2 = new Date(0);
System.out.println(d2);
这里的 0 表示:
- 1970 年 1 月 1 日 00:00:00(UTC)开始计算的毫秒数
3. 获取时间戳
java
Date d = new Date();
System.out.println(d.getTime());
getTime() 返回的是:
- 当前时间距离时间原点的毫秒数
这个值也常被称为:
- 时间戳
4. 设置时间
java
Date d = new Date();
d.setTime(1000);
System.out.println(d);
表示把时间改成时间原点后 1000 毫秒。
5. Date 类的局限
Date 虽然常见,但它本身在很多细节上并不够灵活。
因此在传统 Java 时间处理里,往往会结合 Calendar 一起使用。
十三、Calendar 类
1. Calendar 的作用
Calendar 是一个日历类,用来更灵活地处理日期时间信息,例如:
- 获取某年某月某日
- 获取星期几
- 对日期做加减
相对于 Date,Calendar 在"拆分时间字段"和"修改日期字段"方面更方便。
2. 创建方式
Calendar 是抽象类,通常不能直接 new,而是通过:
java
import java.util.Calendar;
Calendar c = Calendar.getInstance();
3. 获取常见字段
java
System.out.println(c.get(Calendar.YEAR)); // 年
System.out.println(c.get(Calendar.MONTH) + 1); // 月
System.out.println(c.get(Calendar.DAY_OF_MONTH)); // 日
System.out.println(c.get(Calendar.HOUR_OF_DAY)); // 小时
System.out.println(c.get(Calendar.MINUTE)); // 分钟
System.out.println(c.get(Calendar.SECOND)); // 秒
4. 注意月份从 0 开始
这是一个非常经典的坑。
Calendar.MONTH 中:
- 1 月对应
0 - 2 月对应
1 - 12 月对应
11
所以输出月份时,经常要写:
java
c.get(Calendar.MONTH) + 1
5. 修改日期
java
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, 2025);
c.set(Calendar.MONTH, 6); // 实际表示 7 月
c.set(Calendar.DAY_OF_MONTH, 20);
6. 日期加减
java
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, 5); // 加 5 天
c.add(Calendar.MONTH, -1); // 减 1 个月
7. 转为 Date 对象
java
Date d = c.getTime();
这说明:
Calendar和Date可以互相配合使用
十四、Date 与 Calendar 的关系
1. Date 更像"时间点"
Date 更适合表示一个整体时间对象。
2. Calendar 更像"时间工具箱"
Calendar 更适合:
- 拆字段
- 改字段
- 做日期计算
3. 学习阶段怎么理解
可以先简单记住:
- 想直接表示时间,用
Date - 想灵活操作年月日时分秒,用
Calendar
十五、System 类
1. System 是什么
System 是 Java 中一个非常常用的系统工具类。
它提供了很多和系统环境相关的静态方法与静态变量。
最常见的用法有:
- 标准输出
- 获取当前毫秒时间
- 退出程序
- 数组复制
2. System.out.println
这是最熟悉的一种用法:
java
System.out.println("hello");
这里:
System.out是标准输出流println()用于打印并换行
3. currentTimeMillis()
获取当前时间的毫秒值:
java
long time = System.currentTimeMillis();
System.out.println(time);
常见用途:
- 统计程序运行时间
- 获取时间戳
例如:
java
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "ms");
4. exit()
退出程序:
java
System.exit(0);
其中:
0一般表示正常退出
5. arraycopy()
数组复制:
java
int[] src = {1, 2, 3, 4, 5};
int[] dest = new int[5];
System.arraycopy(src, 0, dest, 0, src.length);
参数含义:
- 源数组
- 源起始位置
- 目标数组
- 目标起始位置
- 复制长度
这是一个很高频、很实用的方法。
6. getProperty()
获取系统属性:
java
System.out.println(System.getProperty("java.version"));
System.out.println(System.getProperty("os.name"));
可以用来查看:
- Java 版本
- 操作系统名称
- 用户目录等信息
十六、Runtime 类
1. Runtime 是什么
Runtime 类表示 Java 程序的运行时环境。可以理解为:
它提供了和 JVM 运行环境相关的一些功能。
2. 获取 Runtime 对象
不能直接 new,通常通过:
java
Runtime r = Runtime.getRuntime();
3. 常见方法
获取可用内存
java
Runtime r = Runtime.getRuntime();
System.out.println(r.freeMemory());
获取总内存
java
System.out.println(r.totalMemory());
获取最大内存
java
System.out.println(r.maxMemory());
这些方法可以帮助我们了解 JVM 内存情况。
4. 执行外部程序
java
Runtime r = Runtime.getRuntime();
r.exec("notepad");
这表示调用系统外部程序。
不过这类操作在不同系统环境下要注意命令差异,也可能抛异常。
5. 什么时候会接触 Runtime
初学阶段接触不算特别多,但在以下场景可能会见到:
- 查看 JVM 内存
- 执行外部命令
- 理解 Java 运行环境
十七、Math 类
1. Math 是什么
Math 是 Java 中专门提供数学运算方法的工具类。
它里面的方法大多是静态方法,因此调用时通常直接:
java
Math.方法名(...)
2. 常用方法
绝对值:abs()
java
System.out.println(Math.abs(-10)); // 10
最大值:max()
java
System.out.println(Math.max(10, 20)); // 20
最小值:min()
java
System.out.println(Math.min(10, 20)); // 10
幂运算:pow()
java
System.out.println(Math.pow(2, 3)); // 8.0
平方根:sqrt()
java
System.out.println(Math.sqrt(16)); // 4.0
向上取整:ceil()
java
System.out.println(Math.ceil(3.2)); // 4.0
向下取整:floor()
java
System.out.println(Math.floor(3.8)); // 3.0
四舍五入:round()
java
System.out.println(Math.round(3.6)); // 4
System.out.println(Math.round(3.4)); // 3
随机数:random()
java
System.out.println(Math.random());
返回值范围通常是:
text
[0.0, 1.0)
也就是:
- 包含
0.0 - 不包含
1.0
如果想生成 0~9 的随机整数,可以写成:
java
int num = (int)(Math.random() * 10);
如果想生成 1~10:
java
int num = (int)(Math.random() * 10) + 1;
3. Math 的特点
- 不需要创建对象
- 方法大多是静态的
- 在刷题和开发中都非常常用
十八、这些类在实际开发中的典型使用场景
1. String
适合:
- 输入处理
- 文本拼接
- 字符串查找
- 协议、路径、日志处理
2. BigInteger
适合:
- 超大整数计算
- 大数乘法
- 数学题
3. BigDecimal
适合:
- 金额运算
- 精确小数计算
- 财务场景
4. Date / Calendar
适合:
- 获取当前时间
- 日期计算
- 提取年月日时分秒
5. System
适合:
- 获取毫秒时间
- 打印输出
- 数组复制
- 获取系统属性
6. Runtime
适合:
- 查看 JVM 内存
- 执行外部程序
7. Math
适合:
- 最大最小值
- 绝对值
- 幂运算
- 开方
- 随机数
十九、学习这些工具类时最容易犯的错误
1. 用 == 比较字符串内容
错误示例:
java
if (s1 == s2) {
}
字符串内容比较通常应使用:
java
s1.equals(s2)
2. 忘记 String、BigInteger、BigDecimal 的不可变性
这些类很多方法都会返回新对象。
如果不接收返回值,原变量往往不会改变。
3. 用 double 做金额运算
这会带来精度问题。
金额场景更适合 BigDecimal。
4. 使用 new BigDecimal(0.1)
这容易把浮点误差直接带进去。
更推荐:
java
new BigDecimal("0.1")
5. 忘记 Calendar.MONTH 从 0 开始
这是非常高频的易错点。
6. 把 Math.random() 当成整数随机数
它返回的是 double。
如果想要整数范围,还需要额外转换。
7. 混淆 Date 和 Calendar
它们都和时间有关,但职责并不完全相同。
二十、这些类之间的联系与区别
1. String 和其他类
String 经常和其他类互相配合:
BigInteger(String val)BigDecimal(String val)Integer.parseInt(String s)
很多数据处理的入口和出口,最终都离不开字符串。
2. BigInteger 和 BigDecimal
它们都属于高精度数值类,但侧重点不同:
BigInteger只管大整数BigDecimal负责高精度小数
3. Date 和 Calendar
它们都处理时间:
Date偏向时间点表示Calendar偏向时间字段操作
4. System、Runtime、Math
这三个更像工具类:
System偏系统信息和基础操作Runtime偏运行环境Math偏数学计算
二十一、学习建议
1. 先学"用途",再背方法
不要一上来就死背方法名。
更好的顺序是:
先问这个类解决什么问题
例如:
BigDecimal解决精度问题Math解决常见数学运算Calendar解决时间字段操作
再记常用方法
这样更不容易混乱。
2. 重点掌握高频方法
例如:
String
lengthcharAtsubstringequalssplitindexOf
BigDecimal
addsubtractmultiplydividecompareTo
System
currentTimeMillisarraycopy
Math
absmaxminrandompow
3. 通过小例子反复练
建议自己手写下面这些小程序:
- 判断两个字符串内容是否相等
- 字符串拆分手机号或路径
- 用
BigDecimal计算金额 - 用
Calendar输出当前年月日 - 用
System.currentTimeMillis()测试代码耗时 - 用
Math.random()生成随机数
这些练习都不复杂,但非常有用。
二十二、本章知识总结
1. String 类
String 是 Java 中最常用的字符串类。它的特点是:
- 使用频率高
- 支持字符串常量池
- 具有不可变性
常见方法包括:
lengthcharAtsubstringequalsreplacesplit
2. BigInteger
BigInteger 用于处理任意精度的整数。
适合超大整数运算。
3. BigDecimal
BigDecimal 用于处理高精度小数。
特别适合金额和精确十进制计算。
4. Date 与 Calendar
Date:表示一个时间点Calendar:更灵活地操作年月日时分秒等字段
5. System
System 是系统工具类,常见功能包括:
- 标准输出
- 获取当前毫秒值
- 数组复制
- 退出程序
6. Runtime
Runtime 用于获取 JVM 运行时环境相关信息,例如:
- 内存情况
- 执行外部命令
7. Math
Math 提供常用数学运算方法,例如:
- 绝对值
- 最大最小值
- 幂运算
- 开方
- 随机数
二十三、结语
Java 中的这些常用工具类,看起来不像继承、多态、异常那样"概念化",但它们在实际编程中的出现频率却非常高。
很多时候,真正提高编码效率的,并不是多写多少复杂语法,而是能不能在合适的时候想到合适的工具类。
例如:
- 处理文本,想到
String - 处理大整数,想到
BigInteger - 处理金额,想到
BigDecimal - 处理时间,想到
Date和Calendar - 处理系统信息,想到
System - 做数学运算,想到
Math
这说明学习工具类的本质,不只是记住几个 API,而是慢慢形成一种编程习惯:
- 遇到问题,先判断 Java 是否已经提供了合适的类
- 再决定如何调用这些类中的方法
只有这样,代码才能写得更简洁、更规范,也更符合 Java 的开发思路。
因此,这一章不适合死记硬背,而应该通过大量小例子反复练习。
当你真正把这些常用类用顺手以后,后面的集合、IO、网络编程和项目开发也会轻松很多。
二十四、附:常见语法速查表
1. String
java
String s = "hello";
s.length();
s.charAt(0);
s.substring(1, 3);
s.equals("hello");
s.split(",");
2. BigInteger
java
BigInteger a = new BigInteger("100");
BigInteger b = new BigInteger("200");
a.add(b);
a.subtract(b);
a.multiply(b);
a.divide(b);
3. BigDecimal
java
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
a.add(b);
a.subtract(b);
a.multiply(b);
a.divide(b, 2, BigDecimal.ROUND_HALF_UP);
4. Date
java
Date d = new Date();
d.getTime();
5. Calendar
java
Calendar c = Calendar.getInstance();
c.get(Calendar.YEAR);
c.get(Calendar.MONTH) + 1;
c.add(Calendar.DAY_OF_MONTH, 1);
6. System
java
System.out.println("hello");
System.currentTimeMillis();
System.arraycopy(src, 0, dest, 0, len);
System.exit(0);
7. Runtime
java
Runtime r = Runtime.getRuntime();
r.freeMemory();
r.totalMemory();
r.maxMemory();
8. Math
java
Math.abs(-1);
Math.max(1, 2);
Math.min(1, 2);
Math.pow(2, 3);
Math.sqrt(16);
Math.random();