05常用类

发布时间:2026/11/3 2:24:03
05常用类

包装类

在Java中,包装类(Wrapper Class)是用于将基本数据类型封装为对象的类。每个基本数据类型都有一个对应的包装类,这些类位于java.lang包中,主要用于在需要对象的场景中使用基本数据类型。

基本数据类型与对应包装类

基本数据类型对应包装类
booleanBoolean
charCharacter
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble

Integer 类的常用方法

Integer 类是 Java 中用于包装基本数据类型int的一个类,提供了丰富的静态和实例方法,用于数值处理、类型转换、进制转换等操作。

基本数据类型→包装类对象

Integer a = new Integer(3); Integer b = Integer.valueOf(30);

包装类对象→基本数据类型

Integer b = 123; // 假设 b 是一个 Integer 对象 int c = b.intValue(); // 将 Integer 转换为 int 类型 double d = b.doubleValue(); // 将 Integer 转换为 double 类型

字符串→包装对象

Integer e = new Integer("9999"); Integer f = Integer.parseInt("9999");

包装对象→字符串

String str = f.toString();

MIN_VALUE / MAX_VALUE

int min = Integer.MIN_VALUE; // -2147483648 int max = Integer.MAX_VALUE; // 2147483647

自动装箱与拆箱

在Java中,自动装箱(Autoboxing)是指将基本数据类型(如int、double、boolean等)自动转换为对应的包装类对象(如Integer、Double、Boolean等)。自动拆箱(Unboxing)则是将包装类对象自动转换回对应的基本数据类型。

自动装箱

当基本数据类型被赋值给其对应的包装类引用时,Java编译器会自动调用包装类的静态工厂方法进行转换。

Integer num = 10; // 自动装箱:int → Integer Double price = 3.14; // 自动装箱:double → Double Boolean flag = true; // 自动装箱:boolean → Boolean

上述代码等价于:

Integer num = Integer.valueOf(10); Double price = Double.valueOf(3.14); Boolean flag = Boolean.valueOf(true);

自动拆箱

当包装类对象被用于需要基本数据类型的表达式中时,编译器会自动调用包装类的实例方法提取值。

Integer num = 20; int value = num; // 自动拆箱:Integer → int double d = num; // 自动拆箱:Integer → double(通过提升)

上述代码等价于:

int value = num.intValue(); double d = num.doubleValue();

注意事项

  1. 性能开销
    自动装箱和拆箱涉及对象创建与方法调用,频繁使用可能带来性能损耗,尤其是在循环中。

  2. 空指针异常风险
    若包装类变量为null,自动拆箱会导致NullPointerException。

    Integer a = null; int b = a; // 运行时抛出 NullPointerException
  3. Integer缓存机制
    Integer.valueOf(int)对于 -128 到 127 之间的值会返回缓存对象,因此比较时应使用equals()或注意使用==的陷阱。

    Integer a = 100; Integer b = 100; System.out.println(a == b); // true(来自缓存) Integer c = 200; Integer d = 200; System.out.println(c == d); // false(不同对象)
  • 避免在性能敏感的循环中频繁进行装箱/拆箱。
  • 使用Objects.equals()比较包装类对象,避免空指针。
  • 在比较包装类值时,优先使用.equals()而非==。
  • 明确处理可能为null的情况,防止运行时异常。

StringBuilder 与 StringBuffer类

StringBuilder和StringBuffer都是 Java 中用于动态构建字符串的可变字符序列类,它们都继承自AbstractStringBuilder。

可变性

StringBuilder和StringBuffer的核心优势在于其可变性。与不可变的String类不同,它们允许在不创建新对象的情况下修改字符串内容,从而显著提升频繁拼接操作的性能。

StringBuilder sb = new StringBuilder("abcdefg"); System.out.println(Integer.toHexString(sb.hashCode())); // f6f4d33 System.out.println(sb); // abcdefg sb.setCharAt(2, 'm'); System.out.println(Integer.toHexString(sb.hashCode())); // f6f4d33 System.out.println(sb); // abmdefg

线程安全性

StringBuffer的所有关键方法(如append、insert、reverse)都被声明为synchronized,这意味着在多线程环境下,StringBuffer是线程安全的,多个线程可以安全地共享同一个StringBuffer实例而不会引发数据竞争。

StringBuilder没有使用同步机制,因此在单线程环境中性能更高,但在多线程场景下若多个线程同时访问同一实例,可能导致结果不一致或异常行为。

方法一致性

两者支持相同的方法集合,包括:

  • append(Object obj):追加指定对象的字符串表示。
  • insert(int offset, Object obj):在指定位置插入内容。
  • delete(int start, int end):删除指定范围内的字符。
  • replace(int start, int end, String str):替换指定范围的内容。
  • reverse():反转当前字符序列。
  • toString():返回最终构建的字符串。
StringBuilder sb = new StringBuilder(); sb.append("Hello"); sb.append(" "); sb.append("World"); System.out.println(sb.toString()); // 输出: Hello World StringBuffer sbf = new StringBuffer(); sbf.append("Thread-safe"); sbf.reverse(); System.out.println(sbf.toString()); // 输出: efas-daerhT

性能差异分析

  • String 拼接操作:在循环中使用+拼接字符串时,每次都会生成新的对象,导致大量临时对象堆积,内存开销大,性能下降明显。
  • StringBuilder 拼接操作:通过append()方法直接在内部缓冲区中修改内容,避免了频繁创建新对象,显著提升性能。
// 使用 String 拼接(低效) String result = ""; for (int i = 0; i < 1000; i++) { result += "a"; } // 使用 StringBuilder 拼接(高效) StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.append("a"); } String result = sb.toString();

DateFormat类

格式化日期为字符串

使用SimpleDateFormat类将Date对象格式化为指定格式的字符串。

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String str = df.format(new Date(4000000)); System.out.println(str); // 1970-01-01 09:06:40

解析字符串为日期对象

SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = df2.parse("1990-02-01 18:15:55"); System.out.println(date); // Thu Feb 01 18:15:55 CST 1990

测试其他格式字符

利用D获得本时间对象是所处年份的第几天

SimpleDateFormat df3 = new SimpleDateFormat("D"); String str3 = df3.format(new Date()); System.out.println(str3); // 269

自定义格式符号说明

符号含义
y年份
M月份(大写)
d日期
H小时(0-23)
h小时(1-12)
m分钟
s秒
S毫秒

注意:大小写敏感,MM表示两位月份,M表示一位月份。


Calendar 类

Calendar 类是 Java 中用于处理日期和时间的抽象类,位于java.util包中。它提供了一种灵活的方式来操作日期和时间,支持多种日历系统(如格里高利历),并可以进行日期的加减、比较、格式化等操作。

获取当前日历实例

Calendar calendar = Calendar.getInstance();

设置时间字段

calendar.set(Calendar.YEAR, 2025); calendar.set(Calendar.MONTH, Calendar.APRIL); // 注意:月份从 0 开始,4 表示 5 月 calendar.set(Calendar.DAY_OF_MONTH, 5);

获取时间字段值

int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; // 转换为 1~12 的月份 int day = calendar.get(Calendar.DAY_OF_MONTH);

时间操作(增加/减少)

calendar.add(Calendar.DAY_OF_MONTH, 7); // 向后推 7 天 calendar.add(Calendar.YEAR, -1); // 前移 1 年

比较两个日期

Calendar cal1 = Calendar.getInstance(); cal1.set(2025, Calendar.APRIL, 5); Calendar cal2 = Calendar.getInstance(); cal2.set(2025, Calendar.MAY, 1); if (cal1.compareTo(cal2) < 0) { System.out.println("cal1 在 cal2 之前"); }

与 Date 类的关系

  • Calendar与Date都用于表示时间,但Calendar更强大且可变。
  • Calendar可以直接转换为Date:
Date date = calendar.getTime();
  • Date也可以转换为Calendar:
calendar.setTime(date);
  • Calendar.MONTH从 0 开始(0 表示一月),使用时需注意加 1。
  • Calendar是可变对象,多次操作会修改原实例状态。
  • 推荐在新项目中使用java.time包中的LocalDateTime、ZonedDateTime等现代日期时间类,因为它们更安全、线程友好且语义清晰。

获取时间的方法

public static void printlnCalendar(Calendar c) { int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH) + 1; int day = c.get(Calendar.DAY_OF_MONTH); int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1; String dayOfWeekStr = dayOfWeek == 0 ? "日" : String.valueOf(dayOfWeek); int hour = c.get(Calendar.HOUR); int minute = c.get(Calendar.MINUTE); int second = c.get(Calendar.SECOND); System.out.println(year + "年" + month + "月" + day + "日 周" + dayOfWeekStr + hour + "时" + minute + "分" + second + "秒"); } printlnCalendar(b); // 2026年9月27日 周日6时6分11秒

Math类

Java中的Math类位于java.lang包中,是一个提供基本数学运算方法的工具类。

常见方法

  • Math.abs(x):返回x的绝对值。
  • Math.max(x, y):返回x和y中的较大值。
  • Math.min(x, y):返回x和y中的较小值。
  • Math.ceil(x):向上取整,返回大于等于x的最小整数。
  • Math.floor(x):向下取整,返回小于等于x的最大整数。
  • Math.rint(x):返回最接近x的整数值,若有两个相等的整数,则取偶数。
  • Math.round(x):返回最接近x的long或int值(四舍五入)。
  • Math.trunc(x):截断小数部分,返回整数部分(仅在某些JDK版本支持,建议使用Math.floor或Math.ceil配合类型转换实现)
public class MathExample { public static void main(String[] args) { double a = 16.0; double b = 3.0; System.out.println("sqrt(16): " + Math.sqrt(a)); // 4.0 System.out.println("pow(2, 3): " + Math.pow(2, 3)); // 8.0 System.out.println("max(5, 10): " + Math.max(5, 10)); // 10 System.out.println("min(5, 10): " + Math.min(5, 10)); // 5 System.out.println("sin(π/2): " + Math.sin(Math.PI / 2)); // 1.0 System.out.println("random: " + Math.random()); // 0.0 ~ 1.0 System.out.println("round(3.7): " + Math.round(3.7)); // 4 } }

随机数生成

Math.random():返回一个介于0.0(含)到1.0(不含)之间的双精度浮点数

int randomNum = (int)(Math.random() * 100);
  • 所有方法均为静态方法,无需创建Math对象即可调用。
  • 参数和返回值多为double类型,注意类型转换。
  • 某些方法在输入无效时会返回特殊值,如Math.sqrt(-1)返回NaN。
  • Math.random()不支持自定义范围,需手动扩展。
  • 高精度计算应考虑使用BigDecimal而非Math类。

Random类

Java中的Random类位于java.util包中,用于生成伪随机数。它提供了多种方法来生成不同类型的随机数,适用于需要随机性场景的程序开发。

生成随机整数

使用nextInt()方法可以生成一个介于0(包括)和指定值(不包括)之间的随机整数。例如:

Random random = new Random(); int randomNumber = random.nextInt(10); // 生成0到9之间的随机整数

若需生成指定范围内的随机整数,如5到15之间,可采用以下方式:

int min = 5; int max = 15; int randomNumber = random.nextInt(max - min + 1) + min;

生成随机浮点数

nextDouble()方法返回一个介于0.0(包括)和1.0(不包括)之间的双精度浮点数。

double randomDouble = random.nextDouble(); // 0.0 <= randomDouble < 1.0

若需生成指定范围内的浮点数,例如2.5到7.5之间:

double min = 2.5; double max = 7.5; double randomDouble = min + (max - min) * random.nextDouble();

生成随机布尔值

nextBoolean()方法返回一个随机的布尔值,真或假的概率各为50%。

boolean randomBoolean = random.nextBoolean();

生成随机长整数

nextLong()方法生成一个64位的随机长整数。

long randomLong = random.nextLong();

线程安全性

Random类不是线程安全的。在多线程环境中,建议每个线程使用独立的Random实例,或使用ThreadLocalRandom替代。

import java.util.concurrent.ThreadLocalRandom; // 推荐在多线程中使用 int randomValue = ThreadLocalRandom.current().nextInt(1, 100);

File类

Java中的File类位于java.io包中,是用于表示文件和目录路径名的抽象表示。它不直接操作文件内容,而是提供对文件系统中文件和目录的属性、路径、权限等信息的访问与管理。

创建File对象

通过构造函数创建File实例,可以指定文件或目录的路径:

File file = new File("example.txt"); File directory = new File("/home/user/documents"); File nested = new File("/home/user", "documents/file.txt");

支持绝对路径和相对路径,路径分隔符在不同操作系统中自动适配(如Windows使用\,Unix/Linux使用/)。

判断文件类型

boolean isFile = file.isFile(); // 是否为文件 boolean isDirectory = file.isDirectory(); // 是否为目录

检查是否存在

boolean exists = file.exists();

创建文件或目录

boolean created = file.createNewFile(); // 仅适用于文件,若已存在则返回false boolean dirCreated = directory.mkdir(); // 创建单级目录 boolean dirCreated2 = directory.mkdirs(); // 创建多级目录(包括父目录)

获取文件信息

String name = file.getName(); // 获取文件名 String path = file.getPath(); // 获取路径字符串 String absolutePath = file.getAbsolutePath(); // 获取绝对路径 long lastModified = file.lastModified(); // 最后修改时间(毫秒) long length = file.length(); // 文件大小(字节),若为目录则返回0

文件重命名与移动

File newFile = new File("newname.txt"); boolean renamed = file.renameTo(newFile);

该方法可实现文件重命名或移动到其他目录,前提是目标位置不存在且权限允许。

删除文件或目录

boolean deleted = file.delete(); // 只能删除文件或空目录

若要删除非空目录,需先递归删除其内部所有内容。

遍历目录内容

File dir = new File("/path/to/directory"); String[] files = dir.list(); // 返回文件名数组 File[] allFiles = dir.listFiles(); // 返回File对象数组

配合过滤器可筛选特定类型文件:

File[] txtFiles = dir.listFiles((d, name) -> name.endsWith(".txt"));

路径处理与标准化

File canonicalFile = file.getCanonicalFile(); // 获取规范路径(消除符号链接、相对路径等) File parentDir = file.getParentFile(); // 获取父目录
  • File类本身不涉及文件读写操作,读写需结合InputStream、OutputStream、Reader、Writer等流类。
  • 在多线程环境下,File对象不可变,但其对应文件可能被外部修改。
  • 使用File类时需注意异常处理,例如文件访问权限不足可能导致失败。

mkdir和mkdirs

mkdir是 Javajava.io.File类中的一个方法,用于创建单个目录。该方法仅在父目录存在且目标路径不存在时成功创建目录,否则返回 false。

mkdirs也是 Javajava.io.File类中的方法,功能与mkdir类似,但具有递归创建目录的能力。它会自动创建所有必需的父目录,直到路径完整。

File f3 = new File("d:/电影/港台/陈奕迅"); boolean flag1 = f3.mkdir(); System.out.println(flag1); // false boolean flag2 = f3.mkdirs(); System.out.println(flag2); // true

递归打印目录树结构

public class TestFile1 { public static void main(String[] args) { File f = new File("D:\\7-Zip"); printlnFile(f, 0); } static void printlnFile(File f, int level) { for (int i = 0; i < level; i++) { System.out.print("-"); } System.out.println(f.getName()); if (f.isDirectory()) { File[] files = f.listFiles(); if (files != null) { for (File file : files) { printlnFile(file, level + 1); } } } } }

枚举

语法结构

在 Java 中,枚举(enum)是一种特殊的数据类型,用于定义一组命名的常量。通过enum关键字可以声明一个枚举类型。

public enum 枚举名 { 枚举体1(参数列表), 枚举体2(参数列表), 枚举体3(参数列表); // 构造函数 private 枚举名(参数类型 参数) { // 初始化逻辑 } // 其他方法或字段 public 参数类型 获取方法() { // 返回逻辑 } }

定义一个表示颜色的枚举

public enum Color { RED("红色", 0xFF0000), GREEN("绿色", 0x00FF00), BLUE("蓝色", 0x0000FF); private final String name; private final int rgb; Color(String name, int rgb) { this.name = name; this.rgb = rgb; } public String getName() { return name; } public int getRgb() { return rgb; } }
public class Main { public static void main(String[] args) { Color color = Color.RED; System.out.println("颜色名称: " + color.getName()); System.out.println("RGB值: " + Integer.toHexString(color.getRgb())); } }
颜色名称: 红色 RGB值: ff0000
  • 枚举常量必须在第一行声明,且以分号结尾。
  • 枚举可以包含构造函数、方法和字段。
  • 枚举默认是public static final,不可被继承。
  • 可通过values()方法获取所有枚举值的数组。
  • 可通过valueOf(String)方法根据名称获取枚举实例。