☰
[Java] 常用工具类
2026/10/13 3:21:35 网站建设 项目流程

日期相关类

Date 类

  1. java.util.Date:Java 早期的日期时间类,精确到毫秒,用来表示一个特定的时刻


  2. 常用成员方法
    可用方法:
    1)boolean after(Date when):判断当前日期是否在指定日期之后
    2)boolean before(Date when):判断当前日期是否在指定日期之前
    3)int compareTo(Date anotherDate):比较两个 Date,返回正负 / 0
    4)boolean equals(Object obj):比较两个时间是否相等
    5)static Date from(Instant instant):Instant 转 Date

LocalDateTime


  1. LocalDateTime是Java 8引入的日期时间类,不可变类,
    没有时区信息,只保存日期 + 时间(年、月、日、时、分、秒)
  2. 构造方法是private私有,不能直接new创建对象,只能通过静态方法获取实例
    //私有构造 private LocalDateTime(LocalDate date, LocalTime time) { this.date = date; this.time = time; }

创建 LocalDateTime 对象


  • //1. 获取当前系统日期时间 LocalDateTime now = LocalDateTime.now(); //2. 指定年月日时分,创建时间 LocalDateTime dateTime = LocalDateTime.of(2023, 5, 15, 10, 30); //3. 解析字符串(默认格式:yyyy-MM-ddTHH:mm:ss) LocalDateTime parsed = LocalDateTime.parse("2023-05-15T10:30:00");
  • //1.1 获取当前日期时间 LocalDateTime now= LocalDateTime.now(); System.out.println("当前日期 now(): "+now); // 1.2 指定年月日时分创建 LocalDateTime dateTimeOf=LocalDateTime.of(2026,10,11,13,56,30); System.out.println("of指定时间:"+dateTimeOf); // 1.3 默认格式字符串解析 LocalDateTime parsedDefault=LocalDateTime.parse("2026-10-11T13:56:20"); System.out.println("默认parse解析:"+parsedDefault);


获取当前日期时间

  • //1.1 获取当前日期时间 LocalDateTime now= LocalDateTime.now(); System.out.println("当前日期 now(): "+now);

获取 年、月、日、时、分、秒


  • LocalDateTime dateTime=LocalDateTime.now(); int year=dateTime.getYear(); int month=dateTime.getMonthValue(); int day=dateTime.getDayOfMonth(); int hour=dateTime.getHour(); int minute=dateTime.getMinute(); int second=dateTime.getSecond(); System.out.println("年:"+year); System.out.println("月:"+month); System.out.println("日:"+day); System.out.println("时:"+hour); System.out.println("分:"+minute); System.out.println("秒:"+second);


创建指定日期时间 of ()

  • // 1.2 指定年月日时分创建 LocalDateTime dateTimeOf=LocalDateTime.of(2026,10,11,13,56,30); System.out.println("of指定时间:"+dateTimeOf);


自定义字符串解析

  • parse + DateTimeFormatter


  • yyyy:4 位年份
    MM:2 位月份
    dd:2 位日期
    HH:24 小时制小时
    mm:分钟
    ss:秒


  • String stringDate="2026-10-11 14:20:32"; DateTimeFormatter dateTimeFormatter= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime parseTime=LocalDateTime.parse(stringDate,dateTimeFormatter); System.out.println("自定义格式解析结果:"+parseTime);


获取详细时间信息

  • System.out.println("当前日期为:"+dateTime); System.out.println("本周周几(1==周一,7==周日):"+dateTime.getDayOfWeek().getValue()); System.out.println("本月第几天:"+dateTime.getDayOfMonth()); System.out.println("当年第几天:"+dateTime.getDayOfYear());


日期运算

  • (plusXXX /minusXXX)

  • LocalDateTime不可变,调用 plus/minus 方法会返回新对象,原对象不会修改

  • plusDays(1)加 1 天
    minusDays(1)减 1 天
    plusWeeks(1)加 1 周
    minusWeeks(1)减 1 周
    plusMonths(1)加 1 月
    minusMonths(1)减 1 月
    plusYears(1)加 1 年
    minusYears(1)减 1 年

  • // 增减天数 LocalDateTime plus1Day=dateTime.plusDays(1); LocalDateTime minus1Day=dateTime.minusDays(1); System.out.println("增加1天后:"+plus1Day); System.out.println("减少1天后:"+minus1Day); //增减周 LocalDateTime plus1Week=dateTime.plusWeeks(1); LocalDateTime minus1Week=dateTime.minusWeeks(1); System.out.println("增加一周后:"+plus1Week); System.out.println("减少一周后:"+minus1Week); //增减月 LocalDateTime plus1Month=dateTime.plusMonths(1); LocalDateTime minus1Month=dateTime.minusMonths(1); System.out.println("增加一月后:"+plus1Month); System.out.println("减少一月后:"+minus1Month); //增减年 LocalDateTime plus1Year=dateTime.plusYears(1); LocalDateTime minus1Year=dateTime.minusYears(1); System.out.println("增加一年后:"+plus1Year); System.out.println("减少一年后:"+minus1Year);


TemporalAdjusters 时间调节器(获取指定时间)

  • 获取本周周一、周日

    LocalDateTime currentDate=LocalDateTime.now(); //previousOrSame :当前或之前最近的周一 LocalDateTime firstDayOfWeek=currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); //nextOrSame:当前或之后最近的周日 LocalDateTime lastDayOfWeek=currentDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); System.out.println("本周周一:"+firstDayOfWeek); System.out.println("本周周日:"+lastDayOfWeek);

    previousOrSame:寻找当前日期或之前最近的指定星期
    nextOrSame:寻找当前日期或之后最近的指定星期


获取当月第一天、当月最后一天

  • LocalDateTime currentDate1=LocalDateTime.now(); LocalDateTime firstDayOfMonth=currentDate1.with(TemporalAdjusters.firstDayOfMonth()); LocalDateTime lastDayOfMonth=currentDate1.with(TemporalAdjusters.lastDayOfMonth()); System.out.println("当月第一天:"+firstDayOfMonth); System.out.println("当月最后一天:"+lastDayOfMonth);

总结

  • 不可变:每次修改时间都会生成新对象,原对象不变
  • 私有构造:不能 new,只能now()/of()/parse()创建
  • 格式化:DateTimeFormatter线程安全,替代旧SimpleDateFormat
  • 时间调节器 TemporalAdjusters:快速获取月初、月末、周起始等特殊时间
  • 旧Date、Calendar线程不安全,新项目优先使用 Java8 时间 API

BigDecimal


  1. BigDecimal在java.math包,用于高精度数值运算,解决 float/double 浮点丢失精度的问题(double 只能保证 16 位有效数字)
  2. BigDecimal 是不可变类,每次加减乘除都会返回新的 BigDecimal 对象,原对象不会变

构造方法


  1. //传入double 1.99 double 存储不精确 BigDecimal doubleNum=new BigDecimal(1.99); System.out.println(doubleNum); // 1.98999999 //传入字符串 "2.99" 直接精确解析 BigDecimal stringNum=new BigDecimal("2.99"); System.out.println(stringNum); // 2.99
    原理
    new BigDecimal(1.99):

    a)代码里的1.99是 double 字面量,
    double 底层二进制无法精确表示十进制小数,存的是一个近似值
    b)BigDecimal 只是把这个已经不准确的 double 值完整精确还原出来,
    所以输出一长串小数
  2. 开发规范:
    1)不要用 BigDecimal (double) 构造器,
    优先使用字符串构造器new BigDecimal("数字")
    2)如果已经有 double 变量,可以用BigDecimal.valueOf(double值),
    底层会转字符串,避免精度丢失
  3. 比较大小
    1)不要用==、不要直接用equals()
    2)equals():会同时比较数值 + 小数位数,
    new BigDecimal("2.0")和new BigDecimal("2")equals 判断不相等
    3)compareTo(),可以用这个比较
    BigDecimal num1=new BigDecimal("10.0"); BigDecimal num2=new BigDecimal("10"); System.out.println(num1.compareTo(num2)); //返回 0 代表相等,大于0代表num1>num2,小于0代表num1<num2
  4. 常见使用场景
    金额计算(支付、财务)、科学计算,所有要求不能丢失小数精度的场景
  5. 面试考点总结
    1)为什么不用 double 做金额?二进制浮点无法精确表示部分十进制小数,
    存在精度丢失
    2)BigDecimal 构造器,BigDecimal(double)的坑
    3)BigDecimal 是不可变类,运算会产生新对象
    3)比较数值用compareTo,不要 equals
    4)除法必须指定舍入规则,防止除不尽报错

BigDecimal 加减乘方法


  1. BigDecimal a=new BigDecimal("1.35"); BigDecimal b=new BigDecimal("3.22"); //加法 add() BigDecimal addRet=a.add(b); System.out.println(addRet); // 4.57 // 减法 subtract() BigDecimal subRet=a.subtract(b); System.out.println(subRet); //-1.87 // 乘法 multiply() BigDecimal mulRet=a.multiply(b); System.out.println(mulRet); // 4.3470
  2. 核心重点
    1)BigDecimal 是不可变类
    2)a.add(b)不是修改对象a的值,会返回一个全新 BigDecimal 对象,
    原来的a、b保持不变
  3. 三个方法说明

BigDecimal divide () 除法

  1. 报错代码(错误写法)

    BigDecimal a=new BigDecimal("1.35"); BigDecimal b=new BigDecimal("3.22"); BigDecimal divRet=a.divide(b); System.out.println(divRet);


    报错原因
    a.divide(b) 不带保留位数参数时,要求除法结果必须是有限小数

  2. 方案一:指定小数位数 + 舍入模式(最常用)
    BigDecimal a=new BigDecimal("1.35"); BigDecimal b=new BigDecimal("3.22"); //参数1:除数 参数2:保留小数位数 参数3 : 舍入模式 BigDecimal divRet=a.divide(b,4, RoundingMode.HALF_DOWN); System.out.println(divRet);

    1)4:结果保留4 位小数
    2)RoundingMode.HALF_UP:四舍五入,0.5 向上进 1(财务开发最常用)
    3)注意:除法顺序:a.divide(b) 代表 a ÷ b

  3. 全部舍入模式对照表

    面试重点:银行家舍入 HALF_EVEN,很多框架默认用这个,不是传统四舍五入
  4. 方案二:MathContext 方式
    BigDecimal a=new BigDecimal("1.35"); BigDecimal b=new BigDecimal("3.22"); // MathContext第一个参数是 [有效数字位数] 不是小数位数 BigDecimal divRet=a.divide(b,new MathContext(4,RoundingMode.HALF_UP)); // 0.4193 System.out.println(divRet);

    区分重点:
    1)divide(b, 4, HALF_UP):保留 4 位小数(scale=4)
    2)MathContext(4,HALF_UP):总共保留 4 位有效数字(precision=4)
    例:123.45,保留 4 位有效数字 →123.5,和小数位数不是一回事

  5. 除法核心总结
    1)写 BigDecimal 除法严禁直接写a.divide(b),无限小数直接抛异常
    2)业务开发(金额计算)优先用三参数divide
    (除数,保留小数位数, RoundingMode.HALF_UP)

    3)分清「小数位数 scale」和「有效数字 precision」
    4)BigDecimal 不可变,除法返回新对象,原对象不变

BigDecimal 比较:compareTo()

  1. 面试高频考点:不要用==,不要直接用equals(),优先使用compareTo()

  2. 错误示例
    1)例1 equals() 同时比较【数值 + 小数位数(scale)】
    BigDecimal num1=new BigDecimal("2.0"); BigDecimal num2=new BigDecimal("2"); System.out.println(num1.equals(num2)); // false
    原因:
    a)num1的值是2.0,scale=1(1 位小数)
    b)num2的值是2,scale=0(0 位小数)
    c)equals会把数字大小和小数位数一起对比,虽然数值相等,
    但小数位数不一样,返回 false

    2)例2 == 比较对象地址
    ==判断是不是同一个对象,不是比较数值,基本永远不适合 BigDecimal 数值对比
  3. 正确方法:compareTo()
    BigDecimal num1 = new BigDecimal("2.0"); BigDecimal num2 = new BigDecimal("2"); BigDecimal num3=new BigDecimal("3"); int result=num1.compareTo(num2); // 0 System.out.println(result); System.out.println(num1.compareTo(num3)); // -1 num1 < num3 System.out.println(num3.compareTo(num1)); // 1 num3 > num1 System.out.println(num1.compareTo(num2)); // 0 num1==num2

    返回值规则:
    a)result == 0→两个数字大小相等(忽略小数位数)
    b)result > 0→num1 > num2
    c)result < 0→num1 < num2

  4. 业务常用封装写法
    BigDecimal a=new BigDecimal("10.0"); BigDecimal b=new BigDecimal("5"); if(a.compareTo(b)>0) { System.out.println("a大于b"); } else if(a.compareTo(b)<0) { System.out.println("a小于b"); } else { System.out.println("a等于b"); }
  5. 拓展小知识点:BigDecimal.ZERO
    开发中经常和 0 比较,推荐用常量:
    BigDecimal money = new BigDecimal("0.00"); if(money.compareTo(BigDecimal.ZERO) == 0){ System.out.println("金额等于0"); }

    内置常量还有:
    a)BigDecimal.ZERO0
    b)BigDecimal.ONE1
    c)BigDecimal.TEN10

  6. 总结
    1)equals()比较数值 + 小数位数;
    2)compareTo()只比较数值大小,业务开发比较 BigDecimal 数值必须用compareTo()

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询