【Java 基础编程】Java 常用类速查:包装类、String/StringBuilder、Math、日期类一篇搞定
常用类是 Java 开发中频繁使用的工具类,掌握这些类的使用方法和特点能够提高开发效率,编写更加规范的代码。
⚡ 快速参考
- 包装类:将基本类型封装成对象,支持自动装箱和拆箱
- String 类:不可变字符串,使用
+拼接会创建新对象 - StringBuffer:可变字符串,线程安全,适合多线程环境
- StringBuilder:可变字符串,线程不安全,性能更高,推荐使用
- Math 类:提供数学运算的静态方法
- 日期类:Date、Calendar、LocalDateTime(Java 8+)
📚 学习目标
- 理解包装类的概念和自动装箱拆箱机制
- 掌握 String 类的常用方法和不可变性
- 理解 String、StringBuffer、StringBuilder 的区别
- 掌握 Math 类的常用方法
- 掌握日期类的使用和格式化
一、常用类概述
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之前):
// 手动装箱int n1 =100;Integer integer1 =newInteger(n1);// 方式1Integer integer2 =Integer.valueOf(n1);// 方式2(推荐)// 手动拆箱int n2 = integer1.intValue();自动装箱拆箱(JDK 5之后,推荐):
// 自动装箱int n1 =100;Integer integer = n1;// 底层:Integer.valueOf(n1)// 自动拆箱int n2 = integer;// 底层:integer.intValue()2.4 包装类型转换
包装类 ↔ String:
// Integer → StringInteger i =100;String s1 = i +"";// 方式1String s2 = i.toString();// 方式2String s3 =String.valueOf(i);// 方式3(推荐)// String → IntegerString s ="123";Integer i1 =Integer.parseInt(s);// 方式1(自动装箱)Integer i2 =newInteger(s);// 方式22.5 Integer 常用方法
// 常量System.out.println(Integer.MIN_VALUE);// -2147483648System.out.println(Integer.MAX_VALUE);// 2147483647// 方法Integer.parseInt("123");// 字符串转intInteger.valueOf("123");// 字符串转IntegerInteger.toBinaryString(10);// 十进制转二进制字符串Integer.toHexString(255);// 十进制转十六进制字符串2.6 Character 常用方法
Character.isDigit('5');// 判断是否是数字Character.isLetter('a');// 判断是否是字母Character.isUpperCase('A');// 判断是否是大写Character.isLowerCase('a');// 判断是否是小写Character.isWhitespace(' ');// 判断是否是空白字符Character.toUpperCase('a');// 转大写Character.toLowerCase('A');// 转小写2.7 包装类的缓存机制
Integer 缓存: -128 ~ 127
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类
3.1 String 的特点
特点:
- String 对象用于保存字符串(字符序列)
- 字符串使用 Unicode 编码,一个字符占 2 个字节
- String 是 final 类,不能被继承
- String 实现了 Serializable(可序列化)、Comparable(可比较)接口
- 底层是
char[] value(JDK 8)或byte[] value(JDK 9+) - String 是不可变的(value 数组是 final 的)
3.2 String 的创建方式
方式一:直接赋值(推荐)
String s1 ="hello";// 指向常量池String s2 ="hello";// 复用常量池中的对象System.out.println(s1 == s2);// true方式二:使用构造器
String s3 =newString("hello");// 在堆中创建对象String s4 =newString("hello");// 在堆中创建新对象System.out.println(s3 == s4);// false内存分析:
栈 常量池 堆 s1 ────→ "hello" s2 ────→ ↑ s3 ────────────────→ String对象 ──→ "hello" s4 ────────────────→ String对象 ──→ "hello" 3.3 String 的拼接
规则:
- 常量相加:在常量池
- 变量相加:在堆中(通过 StringBuilder 实现)
// 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);// false3.4 String 常用方法
判断类:
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(是否包含)查找类:
String s ="hello world"; s.length();// 11(字符串长度) s.charAt(0);// 'h'(获取指定索引的字符) s.indexOf('o');// 4(第一次出现的索引) s.lastIndexOf('o');// 7(最后一次出现的索引)提取类:
String s ="Hello World"; s.substring(6);// "World"(从索引6到末尾) s.substring(0,5);// "Hello"(从索引0到5,不含5)转换类:
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"(替换字符串)分割类:
String s ="apple,banana,orange";String[] arr = s.split(",");// ["apple", "banana", "orange"]// 特殊字符需要转义String s2 ="a|b|c";String[] arr2 = s2.split("\\|");// ["a", "b", "c"]转换为字符数组:
String s ="hello";char[] chars = s.toCharArray();// ['h', 'e', 'l', 'l', 'o']格式化字符串:
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.503.5 String 常见面试题
题目1:创建了几个对象?
String s =newString("hello");答案: 2个
- 常量池中的 “hello”
- 堆中的 String 对象
题目2:下面代码的输出?
String s1 ="hello";String s2 ="hello";String s3 =newString("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类
4.1 StringBuffer 的特点
特点:
- 代表可变的字符序列
- 线程安全(方法加了 synchronized)
- 效率比 String 高(修改时不创建新对象)
- 底层:
char[] value(可变数组) - 是 final 类,不能被继承
4.2 String vs StringBuffer
| 特性 | String | StringBuffer |
|---|---|---|
| 可变性 | 不可变 | 可变 |
| 线程安全 | 安全 | 安全 |
| 效率 | 低(频繁创建对象) | 高 |
| 使用场景 | 字符串不变 | 频繁修改 |
4.3 StringBuffer 的创建
// 方式1:无参构造器(初始容量16)StringBuffer sb1 =newStringBuffer();// 方式2:指定容量StringBuffer sb2 =newStringBuffer(100);// 方式3:通过字符串创建StringBuffer sb3 =newStringBuffer("hello");4.4 String 和 StringBuffer 的转换
String → StringBuffer:
String str ="hello";// 方式1:使用构造器StringBuffer sb1 =newStringBuffer(str);// 方式2:使用 append()StringBuffer sb2 =newStringBuffer(); sb2.append(str);StringBuffer → String:
StringBuffer sb =newStringBuffer("hello");// 方式1:使用 toString()(推荐)String s1 = sb.toString();// 方式2:使用构造器String s2 =newString(sb);4.5 StringBuffer 常用方法
StringBuffer sb =newStringBuffer("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类
5.1 StringBuilder 的特点
特点:
- 代表可变的字符序列
- 线程不安全(方法没有 synchronized)
- 效率最高
- 底层:
char[] value(可变数组) - 与 StringBuffer 方法完全相同
5.2 三者对比
| 特性 | String | StringBuffer | StringBuilder |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 安全 | 安全 | 不安全 |
| 效率 | 低 | 较高 | 最高 |
| 使用场景 | 少量修改 | 多线程频繁修改 | 单线程频繁修改 |
效率测试:
long start =System.currentTimeMillis();// String:最慢String s ="";for(int i =0; i <100000; i++){ s += i;}// StringBuffer:较快StringBuffer sb =newStringBuffer();for(int i =0; i <100000; i++){ sb.append(i);}// StringBuilder:最快StringBuilder sbd =newStringBuilder();for(int i =0; i <100000; i++){ sbd.append(i);}long end =System.currentTimeMillis();效率: StringBuilder > StringBuffer > String
5.3 使用原则
选择建议:
- 字符串很少修改 → String
- 单线程大量修改 → StringBuilder(推荐)
- 多线程大量修改 → StringBuffer
六、Math类
6.1 Math 常用方法
// 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);// 4Math.round(3.4);// 3// 7. random():随机数 [0, 1)Math.random();// 0.xxxx// 8. max()、min():最大最小值Math.max(10,20);// 20Math.min(10,20);// 10// 9. PI、E常量Math.PI;// 3.141592653589793Math.E;// 2.7182818284590456.2 生成随机数
生成 [a, b] 范围的随机整数:
// 公式:(int)(Math.random() * (b - a + 1)) + a// 示例:生成 [10, 20] 的随机数int num =(int)(Math.random()*11)+10;七、日期类
7.1 Date 类(第一代)
importjava.util.Date;importjava.text.SimpleDateFormat;// 1. 获取当前时间Date date =newDate();System.out.println(date);// Thu Jan 18 18:30:00 CST 2025// 2. 格式化日期SimpleDateFormat sdf =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateStr = sdf.format(date);System.out.println(dateStr);// 2025-01-18 18:30:00// 3. 字符串 → DateString str ="2025-01-18 18:30:00";Date date2 = sdf.parse(str);7.2 Calendar 类(第二代)
importjava.util.Calendar;// 1. 获取Calendar实例Calendar cal =Calendar.getInstance();// 2. 获取日期信息int year = cal.get(Calendar.YEAR);int month = cal.get(Calendar.MONTH)+1;// 月份从0开始,要+1int 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天7.3 LocalDateTime 类(第三代,JDK 8+,推荐)
importjava.time.LocalDateTime;importjava.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. 字符串 → LocalDateTimeString 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 为什么设计成不可变的?
答案:
- 安全性:String 常用于网络传输、文件路径、参数传递
- 线程安全:不可变对象天然线程安全
- 常量池优化:可以复用对象,节省内存
- hashCode 缓存:不可变,hashCode 只需计算一次
Q2: String、StringBuffer、StringBuilder 的区别?
答案:
| 特性 | String | StringBuffer | StringBuilder |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 安全 | 安全 | 不安全 |
| 效率 | 低 | 较高 | 最高 |
选择建议:
- 少量修改 → String
- 单线程频繁修改 → StringBuilder
- 多线程频繁修改 → StringBuffer
Q3: == 和 equals() 对于 String 的区别?
答案:
==:比较引用(地址)equals():比较内容
String s1 ="hello";String s2 ="hello";String s3 =newString("hello"); s1 == s2;// true(指向同一个常量池对象) s1 == s3;// false(s3 在堆中) s1.equals(s3);// true(内容相同)Q4: String s = new String(“hello”) 创建了几个对象?
答案: 2个
- 常量池中的 “hello”
- 堆中的 String 对象
Q5: String 的 intern() 方法的作用?
答案:
intern() 方法会在常量池中查找是否有相同内容的字符串:
- 如果有,返回常量池中的引用
- 如果没有,将字符串添加到常量池,并返回引用
String s1 ="hello";String s2 =newString("hello");System.out.println(s1 == s2);// falseSystem.out.println(s1 == s2.intern());// true