【第七章】Java中的常用类

【第七章】Java------String类与常用工具类

  • 一、为什么要学习这些常用工具类
    • [1. 它们出现得非常频繁](#1. 它们出现得非常频繁)
    • [2. 它们解决的都是实际问题](#2. 它们解决的都是实际问题)
    • [3. 它们帮助你少造轮子](#3. 它们帮助你少造轮子)
  • [二、String 类概述](#二、String 类概述)
    • [1. 什么是 String](#1. 什么是 String)
    • [2. 为什么 String 这么特殊](#2. 为什么 String 这么特殊)
    • [3. String 的重要地位](#3. String 的重要地位)
  • [三、String 的创建方式](#三、String 的创建方式)
    • [1. 直接赋值](#1. 直接赋值)
    • [2. 使用构造方法](#2. 使用构造方法)
    • [3. 两种写法的区别](#3. 两种写法的区别)
  • 四、字符串常量池
    • [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. 开发中的常见错误)
  • [七、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())
  • [八、String 在刷题和开发中的常见场景](#八、String 在刷题和开发中的常见场景)
    • [1. 遍历字符串](#1. 遍历字符串)
    • [2. 字符串转数字](#2. 字符串转数字)
    • [3. 数字转字符串](#3. 数字转字符串)
    • [4. 判断回文、统计字符、分割路径](#4. 判断回文、统计字符、分割路径)
  • [九、BigInteger 类](#九、BigInteger 类)
  • [十、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 类)
    • [1. Runtime 是什么](#1. Runtime 是什么)
    • [2. 获取 Runtime 对象](#2. 获取 Runtime 对象)
    • [3. 常见方法](#3. 常见方法)
    • [4. 执行外部程序](#4. 执行外部程序)
    • [5. 什么时候会接触 Runtime](#5. 什么时候会接触 Runtime)
  • [十七、Math 类](#十七、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. 混淆 DateCalendar)
  • 二十、这些类之间的联系与区别
    • [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. 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
  • 处理时间时,经常会接触 DateCalendar
  • 获取系统时间、复制数组、退出程序时,常会用到 System
  • 了解当前运行环境、执行外部命令时,会遇到 Runtime
  • 做数学运算时,常会使用 Math

这些类之所以重要,是因为它们几乎覆盖了日常编程中最常见的几类需求:

  • 字符串处理
  • 高精度数值运算
  • 日期时间处理
  • 系统操作
  • 数学计算

如果对这些类不了解,就会经常出现下面这些情况:

  • 不知道为什么字符串明明"改了",结果原变量没变
  • 不知道为什么 0.1 + 0.2 算出来不是严格的 0.3
  • 不知道大整数为什么不能直接用 intlong
  • 不知道时间类之间的关系
  • 不知道 System.currentTimeMillis() 是干什么的
  • 不知道 Math.random()Math.abs()Math.max() 应该怎么用

因此,这一章的学习重点不只是"会调用方法",更重要的是理解这些类分别解决什么问题、适合用在什么场景、使用时有哪些细节要注意。

本章将围绕 Java 中最常见的几个工具类展开说明,重点讲解:

  • String
  • BigInteger
  • BigDecimal
  • Date
  • Calendar
  • System
  • Runtime
  • Math

说明一下:你问题里写的是 data类canlendar类,这里按 Java 中实际常见写法统一讲解为:

  • Date
  • Calendar

通过本章学习,可以掌握:

  • String 的本质与常用方法
  • 字符串为什么具有不可变性
  • 字符串常量池的基本思想
  • BigIntegerBigDecimal 的作用与常用方法
  • 为什么浮点数运算不能直接用于高精度场景
  • DateCalendar 的基本使用方法
  • SystemRuntimeMath 常见方法与应用场景
  • 这些工具类在刷题和开发中的典型用途

一、为什么要学习这些常用工具类

1. 它们出现得非常频繁

Java 中有很多类,但并不是所有类在初学阶段都同样重要。

有些类可能很专业、很细分,而有些类几乎每天写代码都会用到。

比如:

  • 判断字符串长度要用 String.length()
  • 比较字符串内容要用 equals()
  • 金额运算常常要用 BigDecimal
  • 处理大整数常用 BigInteger
  • 获取当前时间常用 DateSystem.currentTimeMillis()
  • 取绝对值、最大值、随机数要用 Math

所以学习这些类,不是"扩展知识",而是"编程必备"。

2. 它们解决的都是实际问题

这些类之所以被设计出来,不是为了增加语法复杂度,而是因为普通基本类型和普通语法解决不了某些现实问题。

例如:

字符串不是普通数组

字符串既要方便比较,又要方便截取、查找、拼接,因此需要专门的 String 类。

金额计算不能随便用 double

因为 double 是二进制浮点数,很多十进制小数无法精确表示,所以需要 BigDecimal

超大整数会超出 long

比如非常大的数字运算,就需要 BigInteger

时间信息很复杂

年月日、时分秒、星期、毫秒这些信息组合在一起,仅靠基本类型很难优雅处理,因此有 DateCalendar 这样的类。

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

原因不是说字符串内容比较,而是:

  • s1s2 指向了常量池中的同一个对象

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)) {
}

这样即使 s1null,也不会报错。


七、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 中整数类型有:

  • byte
  • short
  • int
  • long

它们都属于定长整数。

也就是说,它们能表示的数据范围是有限的。

例如:

  • int 大约是 21 亿范围
  • long 虽然更大,但仍然有限

如果要处理超大整数,例如:

  • 非常大的数学运算
  • 高精度整数计算
  • 大整数乘法

这时 intlong 都不够用,就需要:

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. 注意事项

BigIntegerString 类似,也是不可变对象。

调用方法后会返回新对象,不会直接修改原对象。

例如:

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 是一个日历类,用来更灵活地处理日期时间信息,例如:

  • 获取某年某月某日
  • 获取星期几
  • 对日期做加减

相对于 DateCalendar 在"拆分时间字段"和"修改日期字段"方面更方便。

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();

这说明:

  • CalendarDate 可以互相配合使用

十四、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. 混淆 DateCalendar

它们都和时间有关,但职责并不完全相同。


二十、这些类之间的联系与区别

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

  • length
  • charAt
  • substring
  • equals
  • split
  • indexOf

BigDecimal

  • add
  • subtract
  • multiply
  • divide
  • compareTo

System

  • currentTimeMillis
  • arraycopy

Math

  • abs
  • max
  • min
  • random
  • pow

3. 通过小例子反复练

建议自己手写下面这些小程序:

  • 判断两个字符串内容是否相等
  • 字符串拆分手机号或路径
  • BigDecimal 计算金额
  • Calendar 输出当前年月日
  • System.currentTimeMillis() 测试代码耗时
  • Math.random() 生成随机数

这些练习都不复杂,但非常有用。


二十二、本章知识总结

1. String 类

String 是 Java 中最常用的字符串类。它的特点是:

  • 使用频率高
  • 支持字符串常量池
  • 具有不可变性

常见方法包括:

  • length
  • charAt
  • substring
  • equals
  • replace
  • split

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
  • 处理时间,想到 DateCalendar
  • 处理系统信息,想到 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();

相关推荐
GuWenyue7 小时前
放弃云端API!一套React+WebGPU本地LLM方案,零数据上传、离线可用
前端·人工智能·前端框架
原则猫8 小时前
函数/变量提升
前端
独泪了无痕9 小时前
Vue3 Hooks使用实战解析
前端·vue.js
程序喵大人9 小时前
【C++进阶】STL容器与迭代器 - 01 STL 容器先解决元素放在哪里
开发语言·c++·stl
cui_ruicheng10 小时前
Python从入门到实战(十六):多进程编程
开发语言·python
shawxlee10 小时前
vue3在public下封装config.js自定义配置动态数据,可在打包后直接修改,方便后端部署及后续维护
前端·javascript·经验分享·vue·团队开发·js·项目优化
Jelena1577958579210 小时前
电商运营分析数据比价接口实战:多平台价格监控与智能决策系统
java·大数据·数据库
用户0595401744610 小时前
把记忆存储的回归测试从手工换成 Playwright + GitHub Actions,线上缺陷降低 80%
前端·css
触底反弹11 小时前
🚀 从 DOM0 级到 React 合成事件:前端事件监听的 20 年演进史
前端·react.js·面试