【Java 基础编程】Java 常用类速查:包装类、String/StringBuilder、Math、日期类一篇搞定

常用类是 Java 开发中频繁使用的工具类,掌握这些类的使用方法和特点能够提高开发效率,编写更加规范的代码。

⚡ 快速参考

  • 包装类:将基本类型封装成对象,支持自动装箱和拆箱
  • String 类:不可变字符串,使用 + 拼接会创建新对象
  • StringBuffer:可变字符串,线程安全,适合多线程环境
  • StringBuilder:可变字符串,线程不安全,性能更高,推荐使用
  • Math 类:提供数学运算的静态方法
  • 日期类:Date、Calendar、LocalDateTime(Java 8+)

📚 学习目标

  1. 理解包装类的概念和自动装箱拆箱机制
  2. 掌握 String 类的常用方法和不可变性
  3. 理解 String、StringBuffer、StringBuilder 的区别
  4. 掌握 Math 类的常用方法
  5. 掌握日期类的使用和格式化

一、常用类概述

1.1 什么是常用类?

常用类: Java 提供的一系列工具类,包括包装类、字符串类、数学类、日期类等,用于处理常见的编程任务。

核心类:

  • 包装类:将基本类型封装成对象
  • String 类:处理字符串
  • StringBuffer/StringBuilder:处理可变字符串
  • Math 类:数学运算
  • 日期类:处理日期和时间

二、包装类

2.1 包装类的概念

包装类(Wrapper Class): 将基本数据类型封装成对象。

为什么需要包装类?

  • 基本类型不是对象,无法调用方法
  • 泛型不支持基本类型
  • 需要 null 值表示"无"

2.2 八大包装类

基本类型 包装类 父类
byte Byte Number
short Short Number
int Integer Number
long Long Number
float Float Number
double Double Number
char Character Object
boolean Boolean Object

2.3 装箱和拆箱

装箱: 基本类型 → 包装类
拆箱: 包装类 → 基本类型

手动装箱拆箱(JDK 5之前):

java 复制代码
// 手动装箱
int n1 = 100;
Integer integer1 = new Integer(n1);      // 方式1
Integer integer2 = Integer.valueOf(n1);  // 方式2(推荐)

// 手动拆箱
int n2 = integer1.intValue();

自动装箱拆箱(JDK 5之后,推荐):

java 复制代码
// 自动装箱
int n1 = 100;
Integer integer = n1;  // 底层:Integer.valueOf(n1)

// 自动拆箱
int n2 = integer;  // 底层:integer.intValue()

1.4 包装类型转换

包装类 ↔ String:

java 复制代码
// Integer → String
Integer i = 100;
String s1 = i + "";                // 方式1
String s2 = i.toString();          // 方式2
String s3 = String.valueOf(i);     // 方式3(推荐)

// String → Integer
String s = "123";
Integer i1 = Integer.parseInt(s);  // 方式1(自动装箱)
Integer i2 = new Integer(s);       // 方式2

1.5 Integer 常用方法

java 复制代码
// 常量
System.out.println(Integer.MIN_VALUE);  // -2147483648
System.out.println(Integer.MAX_VALUE);  // 2147483647

// 方法
Integer.parseInt("123");      // 字符串转int
Integer.valueOf("123");       // 字符串转Integer
Integer.toBinaryString(10);   // 十进制转二进制字符串
Integer.toHexString(255);     // 十进制转十六进制字符串

1.6 Character 常用方法

java 复制代码
Character.isDigit('5');       // 判断是否是数字
Character.isLetter('a');      // 判断是否是字母
Character.isUpperCase('A');   // 判断是否是大写
Character.isLowerCase('a');   // 判断是否是小写
Character.isWhitespace(' ');  // 判断是否是空白字符
Character.toUpperCase('a');   // 转大写
Character.toLowerCase('A');   // 转小写

1.7 包装类的缓存机制

Integer 缓存: -128 ~ 127

java 复制代码
Integer a = 127;
Integer b = 127;
System.out.println(a == b);  // true(使用缓存)

Integer c = 128;
Integer d = 128;
System.out.println(c == d);  // false(超出缓存范围,创建新对象)

// 建议:包装类比较使用 equals()
System.out.println(c.equals(d));  // true

三、String类

2.1 String 的特点

特点:

  1. String 对象用于保存字符串(字符序列)
  2. 字符串使用 Unicode 编码,一个字符占 2 个字节
  3. String 是 final 类,不能被继承
  4. String 实现了 Serializable(可序列化)、Comparable(可比较)接口
  5. 底层是 char[] value(JDK 8)或 byte[] value(JDK 9+)
  6. String 是不可变的(value 数组是 final 的)

2.2 String 的创建方式

方式一:直接赋值(推荐)

java 复制代码
String s1 = "hello";  // 指向常量池
String s2 = "hello";  // 复用常量池中的对象
System.out.println(s1 == s2);  // true

方式二:使用构造器

java 复制代码
String s3 = new String("hello");  // 在堆中创建对象
String s4 = new String("hello");  // 在堆中创建新对象
System.out.println(s3 == s4);     // false

内存分析:

复制代码
栈         常量池        堆
s1 ────→  "hello"
s2 ────→    ↑
s3 ────────────────→ String对象 ──→ "hello"
s4 ────────────────→ String对象 ──→ "hello"

2.3 String 的拼接

规则:

  1. 常量相加:在常量池
  2. 变量相加:在堆中(通过 StringBuilder 实现)
java 复制代码
// 1. 常量相加
String s1 = "hello" + "world";  // 编译优化为 "helloworld",在常量池

// 2. 变量相加
String a = "hello";
String b = "world";
String s2 = a + b;  // 在堆中创建新对象

// 底层实现:
// StringBuilder sb = new StringBuilder();
// sb.append(a);
// sb.append(b);
// String s2 = sb.toString();

System.out.println(s1 == s2);  // false

2.4 String 常用方法

判断类:

java 复制代码
String s = "Hello World";

s.equals("hello");          // false(比较内容,区分大小写)
s.equalsIgnoreCase("hello");// true(忽略大小写)
s.isEmpty();                // false(判断是否为空)
s.startsWith("He");         // true(是否以指定字符串开头)
s.endsWith("ld");           // true(是否以指定字符串结尾)
s.contains("lo");           // true(是否包含)

查找类:

java 复制代码
String s = "hello world";

s.length();                 // 11(字符串长度)
s.charAt(0);                // 'h'(获取指定索引的字符)
s.indexOf('o');             // 4(第一次出现的索引)
s.lastIndexOf('o');         // 7(最后一次出现的索引)

提取类:

java 复制代码
String s = "Hello World";

s.substring(6);             // "World"(从索引6到末尾)
s.substring(0, 5);          // "Hello"(从索引0到5,不含5)

转换类:

java 复制代码
String s = "Hello World";

s.toUpperCase();            // "HELLO WORLD"(转大写)
s.toLowerCase();            // "hello world"(转小写)
s.trim();                   // 去除前后空格
s.replace('l', 'L');        // "HeLLo WorLd"(替换字符)
s.replace("World", "Java"); // "Hello Java"(替换字符串)

分割类:

java 复制代码
String s = "apple,banana,orange";
String[] arr = s.split(",");  // ["apple", "banana", "orange"]

// 特殊字符需要转义
String s2 = "a|b|c";
String[] arr2 = s2.split("\\|");  // ["a", "b", "c"]

转换为字符数组:

java 复制代码
String s = "hello";
char[] chars = s.toCharArray();  // ['h', 'e', 'l', 'l', 'o']

格式化字符串:

java 复制代码
String name = "张三";
int age = 20;
double score = 95.5;

String info = String.format("姓名:%s,年龄:%d,成绩:%.2f", name, age, score);
System.out.println(info);  // 姓名:张三,年龄:20,成绩:95.50

2.5 String 常见面试题

题目1:创建了几个对象?

java 复制代码
String s = new String("hello");

答案: 2个

  • 常量池中的 "hello"
  • 堆中的 String 对象

题目2:下面代码的输出?

java 复制代码
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

System.out.println(s1 == s2);      // ?
System.out.println(s1 == s3);      // ?
System.out.println(s1.equals(s3)); // ?

答案:

  • s1 == s2:true(指向同一个常量池对象)
  • s1 == s3:false(s3 在堆中)
  • s1.equals(s3):true(内容相同)

四、StringBuffer类

3.1 StringBuffer 的特点

特点:

  1. 代表可变的字符序列
  2. 线程安全(方法加了 synchronized)
  3. 效率比 String 高(修改时不创建新对象)
  4. 底层:char[] value(可变数组)
  5. 是 final 类,不能被继承

3.2 String vs StringBuffer

特性 String StringBuffer
可变性 不可变 可变
线程安全 安全 安全
效率 低(频繁创建对象)
使用场景 字符串不变 频繁修改

3.3 StringBuffer 的创建

java 复制代码
// 方式1:无参构造器(初始容量16)
StringBuffer sb1 = new StringBuffer();

// 方式2:指定容量
StringBuffer sb2 = new StringBuffer(100);

// 方式3:通过字符串创建
StringBuffer sb3 = new StringBuffer("hello");

3.4 String 和 StringBuffer 的转换

String → StringBuffer:

java 复制代码
String str = "hello";

// 方式1:使用构造器
StringBuffer sb1 = new StringBuffer(str);

// 方式2:使用 append()
StringBuffer sb2 = new StringBuffer();
sb2.append(str);

StringBuffer → String:

java 复制代码
StringBuffer sb = new StringBuffer("hello");

// 方式1:使用 toString()(推荐)
String s1 = sb.toString();

// 方式2:使用构造器
String s2 = new String(sb);

3.5 StringBuffer 常用方法

java 复制代码
StringBuffer sb = new StringBuffer("hello");

// 1. append():追加
sb.append(" world");      // "hello world"
sb.append(123);           // "hello world123"

// 2. delete():删除
sb.delete(5, 11);         // "hello123"(删除索引5到11,不含11)

// 3. replace():替换
sb.replace(0, 5, "hi");   // "hi123"(替换索引0到5)

// 4. indexOf():查找
int index = sb.indexOf("123");  // 2

// 5. insert():插入
sb.insert(2, "aaa");      // "hiaa123"(在索引2处插入)

// 6. length():获取长度
int len = sb.length();    // 7

// 7. reverse():反转
sb.reverse();             // "321aahi"

五、StringBuilder类

4.1 StringBuilder 的特点

特点:

  1. 代表可变的字符序列
  2. 线程不安全(方法没有 synchronized)
  3. 效率最高
  4. 底层:char[] value(可变数组)
  5. 与 StringBuffer 方法完全相同

4.2 三者对比

特性 String StringBuffer StringBuilder
可变性 不可变 可变 可变
线程安全 安全 安全 不安全
效率 较高 最高
使用场景 少量修改 多线程频繁修改 单线程频繁修改

效率测试:

java 复制代码
long start = System.currentTimeMillis();

// String:最慢
String s = "";
for (int i = 0; i < 100000; i++) {
    s += i;
}

// StringBuffer:较快
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 100000; i++) {
    sb.append(i);
}

// StringBuilder:最快
StringBuilder sbd = new StringBuilder();
for (int i = 0; i < 100000; i++) {
    sbd.append(i);
}

long end = System.currentTimeMillis();

效率: StringBuilder > StringBuffer > String

4.3 使用原则

选择建议:

  1. 字符串很少修改 → String
  2. 单线程大量修改 → StringBuilder(推荐)
  3. 多线程大量修改 → StringBuffer

六、Math类

5.1 Math 常用方法

java 复制代码
// 1. abs():绝对值
Math.abs(-10);          // 10

// 2. pow():幂运算
Math.pow(2, 3);         // 8.0(2的3次方)

// 3. sqrt():平方根
Math.sqrt(16);          // 4.0

// 4. ceil():向上取整
Math.ceil(3.1);         // 4.0

// 5. floor():向下取整
Math.floor(3.9);        // 3.0

// 6. round():四舍五入
Math.round(3.5);        // 4
Math.round(3.4);        // 3

// 7. random():随机数 [0, 1)
Math.random();          // 0.xxxx

// 8. max()、min():最大最小值
Math.max(10, 20);       // 20
Math.min(10, 20);       // 10

// 9. PI、E常量
Math.PI;                // 3.141592653589793
Math.E;                 // 2.718281828459045

5.2 生成随机数

生成 [a, b] 范围的随机整数:

java 复制代码
// 公式:(int)(Math.random() * (b - a + 1)) + a

// 示例:生成 [10, 20] 的随机数
int num = (int)(Math.random() * 11) + 10;

七、日期类

6.1 Date 类(第一代)

java 复制代码
import java.util.Date;
import java.text.SimpleDateFormat;

// 1. 获取当前时间
Date date = new Date();
System.out.println(date);  // Thu Jan 18 18:30:00 CST 2025

// 2. 格式化日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = sdf.format(date);
System.out.println(dateStr);  // 2025-01-18 18:30:00

// 3. 字符串 → Date
String str = "2025-01-18 18:30:00";
Date date2 = sdf.parse(str);

6.2 Calendar 类(第二代)

java 复制代码
import java.util.Calendar;

// 1. 获取Calendar实例
Calendar cal = Calendar.getInstance();

// 2. 获取日期信息
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;  // 月份从0开始,要+1
int day = cal.get(Calendar.DAY_OF_MONTH);
int hour = cal.get(Calendar.HOUR_OF_DAY);  // 24小时制
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);

// 3. 设置日期
cal.set(2025, 0, 18);  // 设置为2025年1月18日

// 4. 日期计算
cal.add(Calendar.DAY_OF_MONTH, 10);  // 加10天

6.3 LocalDateTime 类(第三代,JDK 8+,推荐)

java 复制代码
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

// 1. 获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);  // 2025-01-18T18:30:00

// 2. 获取日期信息
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
int hour = now.getHour();
int minute = now.getMinute();
int second = now.getSecond();

// 3. 格式化
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateStr = now.format(dtf);
System.out.println(dateStr);  // 2025-01-18 18:30:00

// 4. 字符串 → LocalDateTime
String str = "2025-01-18 18:30:00";
LocalDateTime ldt = LocalDateTime.parse(str, dtf);

// 5. 日期计算
LocalDateTime future = now.plusDays(10);   // 加10天
LocalDateTime past = now.minusMonths(2);   // 减2个月

八、面试常见问题

Q1: String 为什么设计成不可变的?

答案:

  1. 安全性:String 常用于网络传输、文件路径、参数传递
  2. 线程安全:不可变对象天然线程安全
  3. 常量池优化:可以复用对象,节省内存
  4. hashCode 缓存:不可变,hashCode 只需计算一次

Q2: String、StringBuffer、StringBuilder 的区别?

答案:

特性 String StringBuffer StringBuilder
可变性 不可变 可变 可变
线程安全 安全 安全 不安全
效率 较高 最高

选择建议:

  • 少量修改 → String
  • 单线程频繁修改 → StringBuilder
  • 多线程频繁修改 → StringBuffer

Q3: == 和 equals() 对于 String 的区别?

答案:

  • ==:比较引用(地址)
  • equals():比较内容
java 复制代码
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

s1 == s2;        // true(指向同一个常量池对象)
s1 == s3;        // false(s3 在堆中)
s1.equals(s3);   // true(内容相同)

Q4: String s = new String("hello") 创建了几个对象?

答案: 2个

  1. 常量池中的 "hello"
  2. 堆中的 String 对象

Q5: String 的 intern() 方法的作用?

答案:

intern() 方法会在常量池中查找是否有相同内容的字符串:

  • 如果有,返回常量池中的引用
  • 如果没有,将字符串添加到常量池,并返回引用
java 复制代码
String s1 = "hello";
String s2 = new String("hello");

System.out.println(s1 == s2);          // false
System.out.println(s1 == s2.intern()); // true
相关推荐
AsDuang几秒前
Python 3.12 MagicMethods - 48 - __rmatmul__
开发语言·python
lsx2024061 分钟前
Django 视图 - FBV 与 CBV
开发语言
不会写DN2 分钟前
如何让两个Go程序远程调用?
开发语言·qt·golang
QC班长2 分钟前
如何进行接口性能优化?
java·linux·性能优化·重构·系统架构
啊哈哈121383 分钟前
从零构建 Multi-Agent 系统:SQLAgent + RAGAgent + 智能路由实战
人工智能·python
froginwe113 分钟前
MongoDB 关系
开发语言
聆风吟º3 分钟前
直击复杂 SQL 瓶颈:金仓基于代价的连接条件下推技术落地
java·数据库·sql·kingbasees
墨染天姬7 分钟前
【AI】PyTorch/TF 也会变成考古?
人工智能·pytorch·python
兆子龙1 小时前
ahooks useMemoizedFn:解决 useCallback 的依赖地狱
java·javascript
ん贤3 小时前
Go channel 深入解析
开发语言·后端·golang