JAVA 常用API学习笔记

JAVA API学习笔记

文章目录

  • [JAVA API学习笔记](#JAVA API学习笔记)
    • 一、基础概念
      • [1.1 API概念说明](#1.1 API概念说明)
    • 二、工具类
      • [2.1 Math](#2.1 Math)
      • [2.2 System](#2.2 System)
      • [2.3 Objects](#2.3 Objects)
      • [2.4 Runtime](#2.4 Runtime)
    • 三、字符串相关类
      • [3.1 String](#3.1 String)
      • [3.2 StringBuilder](#3.2 StringBuilder)
      • [3.3 StringJoiner](#3.3 StringJoiner)
      • [3.4 字符串综合练习](#3.4 字符串综合练习)
    • [四、包装类 & 大数类 & Object根父类](#四、包装类 & 大数类 & Object根父类)
      • [4.1 Integer](#4.1 Integer)
      • [4.2 BigInteger](#4.2 BigInteger)
      • [4.3 BigDecimal](#4.3 BigDecimal)
      • [4.4 Object](#4.4 Object)
    • 五、时间API
      • [5.1 JDK7 旧时间API](#5.1 JDK7 旧时间API)
        • 5.1.1Date
        • [5.1.2 SimpleDateFormat](#5.1.2 SimpleDateFormat)
        • [5.1.3 Calendar](#5.1.3 Calendar)
      • [5.2 JDK8 java.time 新时间API](#5.2 JDK8 java.time 新时间API)
        • [5.2.1 时间对象](#5.2.1 时间对象)
        • [5.2.2 格式化类 DateTimeFormatter](#5.2.2 格式化类 DateTimeFormatter)
        • [5.2.3 时间间隔工具类](#5.2.3 时间间隔工具类)

一、基础概念

1.1 API概念说明

核心概念:API = JDK 提供的所有类、接口;工具类是 API 中的一类
分成 4 大模块:工具类、字符串相关、包装 & 大数 & 根父类、时间 API(旧 + 新),结构清晰方便复习。

二、工具类

描述:

  • 构造方法私有,不能 new 创建对象
  • 全部静态,直接类名.方法()调用

2.1 Math

静态方法 作用
public static int abs(int a) 获取参数绝对值
public static double ceil(double a) 向上取整
public static double floor(double a) 向下取整
public static int round(float a) 四舍五入
public static int max(int a,int b) 获取两个 int 最大值
public static double pow(double a , double b) 返回 a 的 b 次幂
public static double random() 返回[0.0,1.0)随机小数
public static double sqrt(double a) 返回平方根
public static double cbrt(double a) 返回立方根
Java 复制代码
int a = 10;
int b = 20;
//加法
System.out.println(a+b); // 30  
//减法
System.out.println(a-b); // -10
//乘法
System.out.println(a*b); // 200
//除法
System.out.println(a/b); // 0
//取模
System.out.println(a%b); // 10
//取绝对值
System.out.println(Math.abs(a)); // 10
//向上取整
System.out.println(Math.ceil(1.1)); // 2.0
//向下取整
System.out.println(Math.floor(1.9)); // 1.0
//四舍五入
System.out.println(Math.round(1.5)); // 2
//获取两个数中较大的值
System.out.println(Math.max(a, b)); // 20
//获取a的b次幂
System.out.println(Math.pow(2, 3)); // 8.0
//获取随机数
System.out.println(Math.random()); // 0.0 ~ 1.0
//获取一个数的平方根
System.out.println(Math.sqrt(4)); // 2.0
//获取一个数的立方根
System.out.println(Math.cbrt(8)); // 2.0

2.2 System

描述:

1:也是一个工具类 提供了一些关于系统的方法

2:时间原点:1970年1月1日0.00 我国在东八区 有八小时误差

3.一秒= 1000毫秒

exit

  • public static void exit(int status) // 状态码0表示正常关闭 非0当前虚拟机异常退出 终止当前虚拟机
java 复制代码
public static void main(String[] args) {
    //关闭虚拟机 (状态码0表示正常关闭 非0当前虚拟机异常退出)
    System.exit(0); // 关闭虚拟机
    System.out.println("看看我执行了吗?");//并没有执行

currentTimeMillis

  • public static long currenttimemills; // 获取当前时间的毫秒值
java 复制代码
long startTime = System.currentTimeMillis();
int count = 100;
while (count > 0) {
    System.out.println("虚拟机运行中..." + count);
    count--;
}
long endTime = System.currentTimeMillis();
System.out.println("虚拟机运行时间:" + (endTime - startTime) + "毫秒");

arraycopy

  • public static void arraycopy(数据源数组,起始位置,目标数组,起始位置,复制的个数)
java 复制代码
int arr1[] = {1, 2, 3, 4, 5};
int arr2[] = new int[5];
System.arraycopy(arr1, 0, arr2, 0, 5);
for (int i = 0; i < arr2.length; i++) {
    System.out.print(arr2[i] + " ");//1 2 3 4 5
}
System.out.println();
  1. 如果数据源数组和目标数组都是基本数据类型 那么两个数组的类型要保持一致 否则会报错
  2. 再拷贝的时候需要考虑数组长度,超出数组则会报错
  3. 如果数据源数组和目标数组是引用数据类型,那么子类数组可以拷贝给父类数组
Java 复制代码
student s1 = new student("张三", 18);
student s2 = new student("李四", 20);
student s3 = new student("王五", 22);
student [] arr = {s1, s2, s3};
father [] arr2 = new father[3];
System.arraycopy(arr, 0, arr2, 0, arr.length);
for (int i = 0; i < arr.length; i++) {
    student s = (student) arr2[i];
    System.out.println(s.name + " " + s.age);
}

2.3 Objects

equal

先判断是否为空 在进行比较

Java 复制代码
    //1.底层逻辑会先判断s1是不是为空 如果s1为空则会返回false 
    //2.如果s1不为空就会使用equals进行比较没有重写方法则会比较地址值 重写了则会比较属性值
        int [] arr = {1,2,3,4,5};
        Student s1 = new Student("张三", 18, "男", arr);
        Student s2 = new Student("张三", 18, "男", arr);
        boolean flag = Objects.equals(s1, s2);
        System.out.println(flag);//true

isnull

nonull

java 复制代码
//判断s1是否为空
 boolean flag2 = Objects.isNull(s1);
 System.out.println(flag2); // false
 //判断s1是否不为空
 boolean flag3 = Objects.nonNull(s1);
 System.out.println(flag3); // true

2.4 Runtime

描述 :表示当前虚拟机的状态 Runtime 代表 Java 程序的运行时环境,不能 new 对象,通过getRuntime()获取实例

getRuntime()

  • public static Runtime getRuntime(); 获取当前系统的运行对象
java 复制代码
Runtime runtime = Runtime.getRuntime();

exit

  • public void exit(0) 停止虚拟机
java 复制代码
Runtime runtime = Runtime.getRuntime();

runtime.exit(0);
System.out.println("看看我执行了吗");//并没有执行 system.exit(0);用的底层代码就是runtime.exit(0);

availableprocessors

  • public int availableProcessors() 获取CPU可用处理器(线程)数量

maxMemory

  • public long maxMemory() JVM最大可从系统申请的内存,单位字节(byte)

totalMemory

  • public long totalMemory() JVM当前已经向系统申请到的内存,单位字节(byte)

freeMemory

  • public long freeMemory() JVM当前空闲可用内存,单位字节(byte)
java 复制代码
        Runtime runtime = Runtime.getRuntime();
//获取cpu的线程数
        System.out.println("Available processors: " + runtime.availableProcessors());
//获取jvm已经从系统中获取的总内存
        System.out.println("Total memory: " + runtime.totalMemory()/1024/1024);//126MB
//获取jvm剩余空闲内存大小
        System.out.println("Free memory: " + runtime.freeMemory()/1024/1024);//122MB
//获取jvm能从系统中获取的最大内存
        System.out.println("Max memory: " + runtime.maxMemory()/1024/1024);//1998MB

exec

  • public Process exec(String command) 执行操作系统cmd/shell命令,返回进程对象Process

**shutdown : 关机 **

加上参数才能执行 -s: 默认一分钟之后关机

​ -s -t 指定时间:指定关机时间

​ -a :取消关机操作

​ -r :关机并重启

java 复制代码
   Runtime runtime = Runtime.getRuntime();
        System.out.println(runtime.exec("shutdown -s -t 3600"));
}//一小时后关机    

三、字符串相关类

3.1 String

介绍

  1. String是Java定义好的一个类。定义在Java.lang包中,使用的时候不需要到导包。
  2. Java程序中的所有字符串文字(例如"abc")都是此类的对象
  3. 字符串不可变,他们的值在创建后不能被更改

创建String对象的方式

1.直接赋值

Java 复制代码
//1.直接赋值字符串
String S1 = "Hello";
System.out.println(S1);//Hello

2.构造方法

public string() 空白字符串 不含任何内容。

public String (字符串) 根据传入的字符串,创建新的字符串对象

public String (char\[\] chs) 根据字符数组,创建字符串对象

public String(byte\[\] chs) 根据字节数组,创建字符串对象

java 复制代码
    //1.通过new关键字
    String S2 = new String("Hello");
    System.out.println(S2);//Hello

    //2.空白字符串,不含有任何字符
    String S3 = new String();
    System.out.println(S3);//""

    //3.通过字符数组赋值
    char[] ch = {'H','e','l','l','o'};
    String S4 = new String(ch);
    System.out.println(S4);//Hello

    //4.通过字节数组赋值
    byte[] b = {72,101,108,108,111};
    String S5 = new String(b);
    System.out.println(S5);//Hello ACSLL表 72----"H"

}

两种创建方式的区别

直接赋值会复用串池里面的内同 new出来的都是一个新的地址

  • String. equals(Object anObject) 比较两个字符串的内容,注意不能为null。

  • equalsIgnoreCase(String anotherString) 与equals方法相似,但忽略大小写。

java 复制代码
public static void main(String[] args) {
    //已知正确账号和密码,请用程序模拟登录系统
    // 一共有三次机会,登录之后会有相应的提示
    String rightnumber = "lisi"; // 已知正确账号
    String rightpassword = "123456"; // 已知正确密码
    //2.键盘输入账号和密码
    Scanner scanner = new Scanner(System.in);
    //3.循环输入账号和密码,判断是否正确
    for (int i = 1; i <= 3; i++) {
        System.out.println("请输入账号:");
        String number = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();
        if (number.equals(rightnumber) && password.equals(rightpassword)) {
            System.out.println("登录成功!");
            break;
        } else {
            if (i == 3){
                System.out.println("账号或密码错误!您已输入错误3次,账号已锁定!");
            }else {
                System.out.println("账号或密码错误!还剩" + (3 - i) + "次机会");
            }
        }
    }

substring

截取字符串:substring(0,3);//截取字符串,包左不包右 (开始索引,结束索引)

​ substring(6);//截取字符串,直接到末尾

字符串本身一旦创建之后,是无法发生改变的。截取时候不会影响调用者的字符串,切记:只有返回值才是截取之后的结果

Java 复制代码
public static void main(String[] args) {
    String str1 = "Hello, World!";
    String result = str1.substring(0, 5);
    System.out.println(result);//Hello
    String str2 = str1 .substring(1);
    System.out.println(str2);//ello, World!
}

Replace

替换 :String replace(旧值,新值)

注意点:只有返回值才是替换后的结果

JAVA 复制代码
   public static void main(String[] args) {
       String str = "你好菜呀,TMD!";
       str = str.replace("TMD", "***");
       System.out.println(str);//你好菜呀,***!
    }
}

Contains

字符串包含判断 contains("是否包含的字符")

Java 复制代码
String str = "abcd";
boolean flag = str.contains("abc");
System.out.println(flag);//true

startsWith()/ endsWith()

判断开头 startsWith("字符") 判断是不是以字符开头

判断结尾 endsWith(("字符")判断是不是以字符结尾

Java 复制代码
String str = "abcd";
//判断开头 startsWith()
boolean flag2 = str.startsWith("ab");
System.out.println(flag2);//true

//判断结尾 endsWith()
boolean flag3 = str.endsWith("cd");
System.out.println(flag3);//true

indexOf()

查找子字符串 indexOf() 查找指定字符第一次出现的位置

java 复制代码
String str = "abcd";
//查找子字符串 indexOf() 查找指定字符第一次出现的位置
int index = str.indexOf("bc");
System.out.println(index);//1

isEmpty()

判断字符串是否为空 isEmpty()

java 复制代码
String str = "abcd";
boolean flag4 = str.isEmpty();
System.out.println(flag4);//false

toUpperCase()/toLowerCase()

转换为大写/转换为小写

java 复制代码
String str = "abcd";
//转换为大写 toUpperCase()
String str2 = str.toUpperCase();
System.out.println(str2);//ABCD

//转换为小写 toLowerCase()
String str3 = str.toLowerCase();
System.out.println(str3);//abcd

toCharArray()

转为字符数组

java 复制代码
char[] charArray = str.toCharArray();
for (char c : charArray) {
    System.out.println(c);
}//abcd

trim

去除头尾空格

java 复制代码
String str4 = "   abcd   ";
String str5 = str4.trim();
System.out.println(str5);//abcd

3.2 StringBuilder

构造方法:带参构造/无参构造

Java 复制代码
StringBuilder sb = new StringBuilder();
System.out.println(sb);//[]

StringBuilder sb2 = new StringBuilder("abc");
System.out.println(sb2);//[abc]

append

JAVA 复制代码
StringBuilder sb = new StringBuilder();
System.out.println(sb);//[]
sb.append("Hello");
System.out.println(sb);//[Hello]

reverse

sb.reverse();反转容器里面的内容

java 复制代码
sb.reverse();
System.out.println(sb);//[olleH]

toString()

sb.toString();把String容器转换为String

java 复制代码
String str = sb.toString();
System.out.println(str);//olleH

3.3 StringJoiner

StringJoiner sj = new StringJoiner("," ,"", "");//间隔符号,开始符号,结束符号 创建一个Stringjoiner容器

add("ccc");//添加元素,只能添加字符串 跟Stringbulid 不同

sj.length();//获取容器长度

sj.toString()//转化为字符串

3.4 字符串综合练习

JAVA 复制代码
    public static void main(String[] args) {
        int arr[] = {1, 2, 3, 4, 5};
        System.out.println(getString(arr));//[1, 2, 3, 4, 5]

    }
    public static String getString(int [] arr) {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < arr.length; i++) {
            sb.append(arr[i]);
            if (i != arr.length - 1) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

1.打印数组

JAVA 复制代码
    public static void main(String[] args) {
        int arr[] = {1, 2, 3, 4, 5};
        System.out.println(getString(arr));//[1, 2, 3, 4, 5]

    }
    public static String getString(int [] arr) {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < arr.length; i++) {
            sb.append(arr[i]);
            if (i != arr.length - 1) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

2.统计字符字数

java 复制代码
package oop01;

import java.util.Scanner;

public class StringDemo01 {
    public static void main(String[] args) {
      //
        // 作业2:写出一个程序,接受一个由数字空格字母组成的字符串,和一个字符,统计这个字符在字符串中出现的次数。
        Scanner sc = new Scanner(System.in);

        System.out.println("请输入一个由数字空格字母组成的字符串");
        String str = sc.nextLine();

        System.out.println("请输入一个字符");
        char ch = getchar(sc);

        int count = getCount(str, ch);
        System.out.println("字符" + ch + "在字符串中出现的次数为:" + count);
    }

    //定义一个方法,统计字符在字符串中出现的次数,不区分大小写
    private static int getCount(String str, char ch) {
        int count = 0;
        ch = Character.toLowerCase(ch);
        for (int i = 0; i < str.length(); i++) {
                if (str.charAt(i) == ch) {
                count++;
            }
        }
        return count;
    }

    //定义一个方法验证输入的字符是否合法,如果输入的字符是空格,则重新输入
    private static char getchar(Scanner sc) {
        while (true){
            char ch = sc.next().charAt(0);
            if (ch!=' '){
                return ch;
            }
            System.out.println("输入错误,请重新输入");
        }
    }
}

3.返回字符串长度

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

public class StringDemo03 {
    //作业3:写出一个程序,接受一个字符串,返回字符串中最后一个字符的长度。
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String str = sc.next();
        int getcount = getcount(str);
        System.out.println("字符串中最后一个字符长度为:" + getcount);
    }

    private static int getcount(String str) {
        //去除头尾空格
        str = str.trim();
        //判断字符串是否为空
        if (str.isEmpty()){
            return 0;
        }
        //找到最后一个空格的位置
        int count = str.lastIndexOf(' ');

        return str.length()-count -1;
    }
}

4.身份证号返回年月日

java 复制代码
  //作业4:写出一个程序,接受一个身份证号码,返回出生年月日和性别。
    public static void main(String[] args) {
        String personpassword = "11010119980515234X";
        StringBuilder sb = new StringBuilder(personpassword);
        String year = sb.substring(6,10);
        String month = sb.substring(10,12);
        String day = sb.substring(12,14);
        System.out.println("出生年月日为:" + year + "年" + month + "月" + day + "日");
        char sex = sb.charAt(16);
        System.out.println("性别为:" + (sex % 2 == 0 ? "女" : "男"));
    }
}

5.整数前后加

java 复制代码
 //将一个字符串中所有的整数前后加上符号"*",其他字符保持不变,连续的数字视为一个整
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String str = "3fda23";
        StringBuilder sb = new StringBuilder(str);
        if (sb.length() > 0 && sb.charAt(sb.length() - 1) >= '0' && sb.charAt(sb.length() - 1) <= '9') {
            sb.append('*');
        }
        for (int i = sb.length()-1; i > 0; i--) {
            char c = sb.charAt(i);
            char test = sb.charAt(i-1);
            if (c == '*') {
                continue;
            }
            if (c >= '0' && c <= '9' && (test < '0' || test > '9')||((test >= '0' && test <= '9' )&& (c < '0' || c > '9'))) {
                sb.insert(i, '*');
            }
        }
        if (sb.length() > 0 && sb.charAt(0) >= '0' && sb.charAt(0) <= '9') {
            sb.insert(0, '*');
        }
        System.out.println(sb.toString());

    }

6.获取验证码

java 复制代码
public static void main(String[] args) {
        //获取一个验证码,验证码由4个大写字母和1个数字组成,且数字可以是任意位置
        System.out.println(getCode());
    }
    public static String getCode() {
        // 创建一个包含所有字母的数组
        char [] arr = new char[52];
        // 填充大写字母
        for (int i = 0; i < arr.length/2; i++) {
            arr[i] = (char)('A' + i);
        }
        // 填充小写字母
        for (int i = arr.length/2; i < arr.length; i++) {
            arr[i] = (char)('a' + i-26);
        }
        // 打印数组

        // 创建一个StringBuilder对象
        StringBuilder sb = new StringBuilder();
        // 随机获取4个字符并添加到StringBuilder中
      for (int i = 0; i < 4; i++) {
           int index = (int)(Math.random() * arr.length);
          sb.append(arr[index]);
           // 随机获取一个数字并添加到StringBuilder中

       }
        int num = (int)(Math.random() * 10);
        sb.append(num);
        char[] ch = sb.toString().toCharArray();
        int index = (int)(Math.random() * ch.length);
            char temp = ch[ch.length - 1];
            ch[ch.length - 1] = ch[index];
            ch[index] = temp;

        return new String(ch);
    }

四、包装类 & 大数类 & Object根父类

4.1 Integer

***获取intger的方法:***构造方法 静态方法 直接赋值

  1. 构造方法
java 复制代码
// 创建Integer对象
//创建新的对象
// 使用new关键字创建对象  每次都会在内存中创建新的对象

Integer i = new Integer(13); // 自版本9起已弃用
Integer i1 = new Integer(13);
System.out.println(i==i1);//false

2.静态方法

Java 复制代码
// 使用valueOf方法创建对象  会使用缓存中的对象
// 会先从缓存中查找,如果找到则返回缓存中的对象,如果找不到则创建新的对象
// 也就是包装类常量池 范围为 -128~127 找不到则会使用new关键字创建新的对象
Integer i2 = Integer.valueOf(127);
Integer i3 = Integer.valueOf(127);
System.out.println(i2==i3);//true
Integer i4 = Integer.valueOf(128);
Integer i5 = Integer.valueOf(128);
System.out.println(i4==i5);//false
  1. 直接赋值
Java 复制代码
//直接赋值  会使用缓存中的对象 valueOf方法简化版
Integer i6 = 127;
Integer i7 = 127;
System.out.println(i6==i7);//true

4.2 BigInteger

java中的大整数

获取方式只有两种 不能直接赋值

Java 复制代码
//1.利用构造方法创建对象
BigInteger bd1 = new BigInteger("10");
BigInteger bd2 = new BigInteger("10");
System.out.println(bd1==bd2) ; // false

//2.利用valueOf方法创建对象 跟integer一样 会有一个缓存区 也就是常量池 范围为(-16到16)一共为33个
//细节:valueOf方法会检查缓存区,如果缓存区中存在该对象,则返回缓存区中的对象,否则返回新创建的对象
//如果获取的数字比较大 超出了long的范围,此时只能用构造方法获取数据
BigInteger bd3 = BigInteger.valueOf(16);
BigInteger bd4 = BigInteger.valueOf(16);
System.out.println(bd3==bd4); // true


BigInteger bd5 = BigInteger.valueOf(17);
BigInteger bd6 = BigInteger.valueOf(17);
System.out.println(bd5==bd6); // false
//3.不能直接赋值,否则会报错

成员方法

进行计算 不会影响原来的值 而是会创建一个新的对象

Java 复制代码
public static void main(String[] args) {
  BigInteger b1 = new BigInteger("10");
  BigInteger b2 = new BigInteger("20");
  //加法
  System.out.println(b1.add(b2)); // 30
  //减法
  System.out.println(b1.subtract(b2)); // -10
  //乘法
  System.out.println(b1.multiply(b2)); // 200

  //除法 取商
    System.out.println(b2.divide(b1)); // 2
  //除法 取商还有余数 返回数组
    BigInteger[] bigIntegers = b2.divideAndRemainder(b1);// [2, 0]
    System.out.println(bigIntegers[0]); // 2
    System.out.println(bigIntegers[1]); // 0
  //取模
   System.out.println(b2.mod(b1)); // 0
   //取余
   System.out.println(b2.remainder(b1)); // 0
   //取最大值
    BigInteger max = b2.max(b1);// 20
    //把最大值b2的地址值赋值给max,max和b2指向同一个对象
    System.out.println(max); // 20
   //次方
    System.out.println(b2.pow(2)); // 400

4.3 BigDecimal

作用: 用来表示较大的小数 和解决小数不精确的问题

java 复制代码
 public static void main(String[] args) {
        //1.   利用构造方法 创建一个BigDecimal对象
        //创建数组 传递数组
        char [] ch = { '1', '2', '3' };
        BigDecimal b1 = new BigDecimal(ch);
        System.out.println(b1);
        // 传递字符串
        BigDecimal b2 = new BigDecimal("123");
        System.out.println(b2); // 123
        // 传递double 会报错 因为double是浮点数 会存在精度问题
        BigDecimal b3 = new BigDecimal(1.123);
        System.out.println(b3);

        //2.利用静态方法创建BigDecimal对象
        // 优化机制 会有一个常量池 {0 -10}
        BigDecimal b4 = BigDecimal.valueOf(1.123);
        System.out.println(b4);//1.123
        BigDecimal b5 = BigDecimal.valueOf(10);
        BigDecimal b6 = BigDecimal.valueOf(10);
        System.out.println(b5==b6);//true

        BigDecimal b7 = BigDecimal.valueOf(11);
        BigDecimal b8 = BigDecimal.valueOf(11);
        System.out.println(b7==b8);//false
//结论:如果在double范围使用静态方法获取对象  超出double范围使用构造方法 (参数必须以字符串形式)

        //常见方法 加减乘除
        BigDecimal b9 = new BigDecimal("30");
        BigDecimal b10 = new BigDecimal("100");
        System.out.println(b9.add(b10)); // 130
        System.out.println(b10.subtract(b9)); // 70
        System.out.println(b9.multiply(b10)); // 3000
        System.out.println(b10.divide(b9)); // 3.3333333333333335 (无限循环) 会报错 因为BigDecimal默认是精确计算的,不允许有余数
        // 取商和余数
        BigDecimal [] arr = b10.divideAndRemainder(b9);
        System.out.println(arr[0]); // 3
        System.out.println(arr[1]); // 10
        // 保留小数位数 四舍五入
        System.out.println(b10.divide(b9, 2, BigDecimal.ROUND_HALF_UP)); // 3.33


    }
}

4.4 Object

所以子类共同的父类

toString

1.返回对象的字符串表示形式

2.当我们打印一个对象的时候,底层会调用对象的toString方法,把对象变成字符串然后再打印在控制台上,打印完毕换行处理

3.默认打印的是地址值,但对于我们是没有意义的,如果我们想看到对象内部的属性值,重写toString方法就可以了

toString 重写位置:自己定义的 Javabean 实体类当中,使用 Alt+Insert 自动生成。

Object 提供原始 toString,返回地址;子类重写,返回对象的属性信息。

Java 复制代码
public class student {
    String name;
    int age;
    String sex;
    public student() {
    }

    public student(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}
Java 复制代码
public static void main(String[] args) throws IOException {
    student a = new student("张三", 18, "男");
    System.out.println(a.toString());//heima.com.ui.student@2f4d3709  重写前
    System.out.println(a);//student{name='张三', age=18, sex='男'}      重写后
} 

equals

1.如果没有重写equals方法,那么默认使用object中的方法进行比较,比较的是地址值

2,一般来讲比较地址值对于我们意义不大,所以我们会进行重写,重写之后比较的就是对象内部的属性值了

Java 复制代码
public class student {
    String name;
    int age;
    String sex;
    public student() {
    }
    public student(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        student student = (student) o;
        return age == student.age && Objects.equals(name, student.name) && Objects.equals(sex, student.sex);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, sex);
    }
}
Java 复制代码
public static void main(String[] args) throws IOException {
    student a = new student("张三", 18, "男");
    student b = new student("张三", 18, "男");
    System.out.println(a == b);//false (重写前比较的是地址值)
    System.out.println(a.equals(b));//true (重写后比较的是对象内部的属性值)
}

拓展

Java 复制代码
  public static void main(String[] args) throws IOException {
        String s = "hello";
        StringBuilder sb = new StringBuilder("hello");
        System.out.println(s.equals(sb));//false
        System.out.println(sb.equals(s));//false
    }
}

equals 笔记总结

  1. Object 的 equals(StringBuilder 直接使用,没有重写)
  • 只做一件事:比较对象地址
  • 地址相同返回 true,不同直接返回 false,没有后续逻辑。
  • StringBuilder 没有重写 equals,所以比较的是地址,不比较字符内容。
  1. String 重写后的 equals 【源码真实执行顺序】

  2. 第一步:this == anObject 判断地址

    • 如果是同一个对象,地址相同 → 直接返回 true,后面代码不执行。
  3. 地址不一样,才执行第二步:instanceof 判断是不是 String 类型

    • 如果不是 String 类型,直接返回 false。
    • 如果是 String,再逐个比较内部每一个字符。
  4. 字符全部相同返回 true,否则返回 false。

源码顺序:先比地址 → 再判断类型 → 最后比较字符

  1. 区分口诀
  • ==:永远比较地址。
  • String.equals:先比地址,地址相同直接 true;地址不同,判断类型,再比内容
  • StringBuilder.equals:等价==只比较对象地址,不比较内容

注意:部分视频讲课会口头先说类型判断,是为突出考点,以 JDK 源码的代码行顺序为准

Clone

1.重写object类的clone方法

Java 复制代码
@Override
protected Object clone() throws CloneNotSupportedException {
    return super.clone();
}

2.让JavaBean实现Cloneable接口

Java 复制代码
public class Student implements Cloneable {
    String name;
    int [] arr;
    int age;
    String sex;
    public Student() {
    }

3,创建原对象并调用clone就可以了

浅克隆

不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来

Java 复制代码
public static void main(String[] args) throws IOException, CloneNotSupportedException {
    // 测试克隆
    //1.先创建一个对象
    int [] arr = {1,2,3,4,5};
    Student s1 = new Student("张三", 18, "男", arr);
    //2.克隆对象
    // 底层会帮我们创建对象,调用的是Object类中的clone方法 并将源对象的内容拷贝过去
    // 步骤  1. 先重写object的clone方法
    //      2. 让Javabean源对象实现Cloneable接口
    //      3. 创建原对象调用clone方法即可
    Student s2 = (Student) s1.clone();
    //验证object里的clone是不是浅克隆 这里已经克隆完成 现在修改s1中的数组 查看s2是否受到影响
    int [] data = s1.arr;
    data[0] = 100;
    //输出s1和s2 结果为浅克隆 s1 中的基本数据类型和字符串是独立的,但引用数据类型是共享的
    // (这里已经在Javabean)中重写了toString 所以会直接打印内容而不是地址值)
    System.out.println(s1);//Student{name='张三', age=18, sex='男'[100, 2, 3, 4, 5]}
    System.out.println(s2);//Student{name='张三', age=18, sex='男'[100, 2, 3, 4, 5]}

}

深克隆

基本数据类型拷贝过来 字符串复用 引用数据类型会重新创建新的

需要重写方法,或者使用第三方工具

java 复制代码
protected Object clone() throws CloneNotSupportedException {
    //1.先把克隆对象的数组获取出来
    int [] data = this.arr;
    //2.再创建新的数组,用于存放克隆对象的数组
    int [] newdata = new int[data.length];
    for (int i = 0; i < data.length; i++) {
        newdata[i] = data[i];
    }
    //3.调用父类中的浅克隆 因为父类中的clone方法是浅克隆 替换克隆出的对象数组地址值
    Student student = (Student) super.clone();
    //4.将新数组赋值给克隆对象的数组
    student.arr = newdata;
    return student;
}

五、时间API

5.1 JDK7 旧时间API

5.1.1Date
  1. 构造方法
  • Date():创建当前系统时间的 Date 对象

  • Date(long time):传入毫秒时间戳,创建对应时间对象(时间戳:1970‑01‑01 00:00:00 GMT 到该时间的毫秒数)

    2.方法

  • getTime():把时间变成毫秒时间戳

  • before/after:比较两个时间谁早谁晚

java 复制代码
//创建对象表示当前时间
Date d1 = new Date();
System.out.println(d1);
//创建对象表示一个指定的时间
Date d2 = new Date(0L);
System.out.println(d2);//Thu Jan 01 08:00:00 CST 1970
//settime设置时间
//1000毫秒 = 1秒
d1.setTime(1000l);//Thu Jan 01 08:00:01 CST 1970
System.out.println(d1);

3.小练习

  • 打印时间原点一年以后的时间
Java 复制代码
private static void extracted() {
    Date d1 = new Date(0);
    System.out.println(d1);//Thu Jan 01 08:00:00 CST 1970
    long time = d1.getTime();
    time = time + 1000l*60*60*24*365;
    d1.setTime(time);
    System.out.println(d1);//Fri Jan 01 08:00:00 CST 1971
}
  • 定义任意两个date对象,比较哪个时间在前,哪个时间在后
Java 复制代码
private static void max() {
    Random r = new Random();
    Date date01 = new Date(Math.abs(r.nextInt()));
    Date date02 = new Date(Math.abs(r.nextInt()));
    System.out.println(date01);
    System.out.println(date02);
    long time01 = date01.getTime();
    long time02 = date02.getTime();
    if (time01 > time02) {
        System.out.println("time01 > time02");

    }else  {
        System.out.println("time01 < time02");
    }
}
5.1.2 SimpleDateFormat

(配合 Date 做格式化解析)

  1. 作用
  • format(Date):Date → 字符串(日期格式化)
  • parse(String):字符串 → Date(日期解析,会抛出ParseException异常)
符号 含义
yyyy 4 位年
MM 2 位月份
dd
HH 24 小时制小时
mm 分钟
ss
E 星期

3.小练习

3.1

Java 复制代码
public static void main(String[] args) throws IOException, CloneNotSupportedException, ParseException {
    //把2020-01-01转换为日期格式并打印
    // 可以理解为将一个字符串时间 从它本身的模板中解析出来,解析出来的叫时间对象 再把时间对象套入新的模板中
    // 1 先定义字符串表示时间
    String str = "2020-01-01";
    // 2 定义与字符串相同的日期格式并进行解析
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Date date = sdf.parse(str);
    // 3 定义新的日期格式并进行转换
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日");

    String dateStr = sdf1.format(date);
    System.out.println(dateStr); // 2020年01月01日

3.2

java 复制代码
/*肯打鸡限时秒杀
1 元秒杀
葡式蛋挞(1 只)兑换券
秒杀开始时间:2023 年 11 月 11 日 0:0:0
秒杀结束时间:2023 年 11 月 11 日 0:10:0
需求
小贾下单并付款的时间为:2023 年 11 月 11 日 0:01:00
小皮下单并付款的时间为:2023 年 11 月 11 日 0:11:0
用代码说明这两位同学有没有参加上秒杀活动?*/
SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日 HH:mm:ss");
Date startTime = sdf.parse("2023 年 11 月 11 日 0:0:0");
Date endTime = sdf.parse("2023 年 11 月 11 日 0:10:0");
Date jiaTime = sdf.parse("2023 年 11 月 11 日 0:01:00");
Date piTime = sdf.parse("2023 年 11 月 11 日 0:11:00");
if (jiaTime.after(startTime) && jiaTime.before(endTime)) {
    System.out.println("小贾参加了秒杀活动");
} else {
    System.out.println("小贾没有参加秒杀活动");
}
if (piTime.after(startTime) && piTime.before(endTime)) {
    System.out.println("小皮参加了秒杀活动");
} else {
    System.out.println("小皮没有参加秒杀活动");
}
5.1.3 Calendar

1.获取方法抽象类,不能 new 对象 ,只能用Calendar.getInstance()拿实例。

Java 复制代码
// 获取当前系统时间的日历对象
Calendar cal = Calendar.getInstance();

*** 和 Date 互相转换**

复制代码
// Calendar → Date
Date date = cal.getTime();

// Date → Calendar
cal.setTime(date);
  • getTime():把日历存的时间,包装成 Date 对象返回(就是你刚才看的代码)
  • setTime(date):把 Date 里面的时间,赋值给 Calendar 日历对象

2.常用方法

get () 获取年月日时分秒(超级大坑)

复制代码
cal.get(Calendar.YEAR);        // 年,正常
cal.get(Calendar.MONTH);       // ⚠️重点坑:月份 **0‑11**!0=1月,11=12月!拿出来要+1才是现实月份
cal.get(Calendar.DAY_OF_MONTH);// 月中的几号(1‑31)
cal.get(Calendar.HOUR_OF_DAY);// 24小时制小时
cal.get(Calendar.MINUTE);     // 分钟
cal.get(Calendar.SECOND);     // 秒

坑:打印月份记得 cal.get(Calendar.MONTH)+1,不然永远少 1 个月。

set () 设置时间

复制代码
// 直接设置 年,月,日,时,分,秒
cal.set(2023,10,11,0,10,0);
// 注意第二个参数月份!10代表11月!不是10月!

// 单独修改某一个字段
cal.set(Calendar.YEAR,2025);

add () 做时间加减(最常用)

修改日历本身对象,会自动进位,比如 12 月加 1 个月自动变成下一年 1 月

复制代码
cal.add(Calendar.DAY_OF_MONTH, 3); // 加3天
cal.add(Calendar.DAY_OF_MONTH, -2); // 减2天
cal.add(Calendar.MONTH, 1); // 加1个月

⚠️Calendar 是可变对象,add、set 直接修改原对象,不是返回新对象!和 Java8 新时间类不一样!

add vs roll(了解)

  • add():会联动进位,12 月 + 1 月 → 下一年 1 月(干活用这个)
  • roll():只改当前字段,不联动年月,几乎不用CSDN博...。

常用常量

常量 含义
Calendar.YEAR
Calendar.MONTH 月份 (0‑11)
Calendar.DAY_OF_MONTH 当月几号
Calendar.DAY_OF_YEAR 一年当中第几天
Calendar.HOUR_OF_DAY 24 小时制小时

细节1.

Calendar是一个抽象类 不能直接new出来 需要用静态方法获取到子类对象

底层原理:会根据系统的不同时区获取不同的日历对象,默认为当前时间

会把时间中的纪元,年,月,日,时,分,秒都放进一个数组中

细节2.

月份:范围0~11 如果获取的是0实际上得到的是一月

星期:在老外眼里星期日就是一周中的第一天 1(星期天) 2(星期一)

java 复制代码
       public static void main(String[] args) {
       
        Calendar c = Calendar.getInstance();
        System.out.println(c.getTime());
        // Date d = new Date(0l);
        // c.setTime(d);
        long timeInMillis = c.getTimeInMillis();//拿到时间毫秒值
        c.setTimeInMillis(0l);//给日历对象设置时间毫秒值
        System.out.println(c.getTime());//Fri Jan 23 14:01:44 CST 2026
        c.set(Calendar.HOUR_OF_DAY,0);//修理日历中某的字段的信息
        c.add(Calendar.DAY_OF_MONTH,1);//为某个字段的信息增加或减少指定的值
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        int week = c.get(Calendar.DAY_OF_WEEK);
        System.out.println(year+" "+month+" "+day+" "+getweek(week));//2026 1 24 星期六
        getweek(week);

    }

    private static String getweek(int week) {
        String arr[] = {"","星期天","星期一","星期二","星期三","星期四","星期五","星期六"};
        return arr[week];
    }

}

3.总结

Calendar 缺点(面试必背)

  1. 月份从 0 开始,巨容易写错 bug
  2. 可变对象:set/add 直接改自己,不是返回新对象
  3. 线程不安全,多线程不能共用同一个 Calendar 实例稀土掘金
  4. API 难用,Java8 以后推荐用 LocalDateTime,新项目尽量不用 Calendar

5.2 JDK8 java.time 新时间API

5.2.1 时间对象

全部来自 java.time都是不可变类,没有 new 构造方法,使用静态方法创建对象

1.ZoneId 时区类

作用:专门存时区信息,比如亚洲上海、纽约时区。

创建对象(没有 new,静态方法)

方法 作用
ZoneId.of("Asia/Shanghai") 通过时区字符串指定时区,上海东八区
ZoneId.systemDefault() 获取本机系统默认时区(我们电脑就是 Asia/
java 复制代码
//1.获取Java中支持的所有时区
Set<String> ZoneIds = ZoneId.getAvailableZoneIds();
System.out.println(ZoneIds);
//2.获取系统默认时区
ZoneId zoneId1 = ZoneId.systemDefault();
System.out.println(zoneId1);
//3.获取一个指定时区
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
System.out.println(zoneId);

白话:只是个时区标签 ,本身没有年月日时分秒

中国时区写:Asia/Shanghai,不要写 + 8。

2. Instant 时间戳(UTC 标准时间)

作用:代表世界标准 UTC 时间线上的一个瞬间,存时间戳(1970‑01‑01 00:00:00 UTC 起算)

1.21创建对象(静态方法,无 new)

方法 功能
Instant.now() 获取当前 UTC 标准时间
Instant.ofEpochMilli(long 毫秒) 用毫秒时间戳构建 Instant(1970 基准)

1.22常用方法

方法 作用
long toEpochMilli() 转成毫秒时间戳
ZonedDateTime atZone(ZoneId zoneId) 给 Instant 套上时区 → 返回 ZonedDateTime
boolean isBefore(Instant other) 比较时间,是否在另一个时间之前
boolean isAfter(Instant other) 比较时间,是否在另一个时间之后
复制代码
Instant ins = Instant.now();
// 加时区
ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());
// 获取毫秒
long ms = ins.toEpochMilli();

和 Date 互转

  • date.toInstant() Date → Instant

  • Date.from(instant) Instant → Date

    Instant now = Instant.now(); // 获取当前UTC时间戳

  • 不带时区!全球同一时刻,Instant 的值完全一样。

  • 新旧时间 API 转换的桥梁:Date ↔ 新时间类,都靠 Instant 中转。

  • 对应老版java.util.Date,Date 底层本质就是 Instant。

白话:全世界统一的 "绝对时间点",没有北京时间、纽约时间概念,就是时间轴上的一个点。

java 复制代码
 //1.获取当前的时间Instant对象
    Instant instant = Instant.now();
    System.out.println(instant);
    //2.根据(秒/毫秒/纳秒)获取Instant对象
    Instant instant1 = Instant.ofEpochMilli(1000l);//根据毫秒获取对象
    System.out.println(instant1);
    Instant instant2 = Instant.ofEpochSecond(1l);//根据秒获取对象
    System.out.println(instant2);//根据秒和纳秒获取对象
    Instant instant3 = Instant.ofEpochSecond(2l, 1000000000l);
    System.out.println(instant3);
    //3.获取指定时区的时间
    ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
    System.out.println(zonedDateTime);
    //isBefore 判断是否在前面
    Instant instant4 = Instant.ofEpochMilli(100l);
    Instant instant5 = Instant.ofEpochSecond(1l);
    boolean result = instant4.isBefore(instant5);
    System.out.println(result);
    //isAfter  判断是否在后面
    boolean result1 = instant4.isAfter(instant5);
    System.out.println(result);
    //4.minusXxx 减少时间系列的方法
    Instant instant7 = Instant.ofEpochSecond(3l);//1970-01-01T00:00:03Z
    Instant instant8 = instant7.minusSeconds(1);
    System.out.println(instant8);//1970-01-01T00:00:02Z
    //5.plusXxx 增加时间系列的方法
    Instant instant9 = instant8.plusSeconds(1);
    System.out.println(instant9);
}

3. ZonedDateTime 带时区的完整时间

= LocalDateTime(年月日时分秒) + ZoneId(时区)

复制代码
// 当前系统时区的带时区时间
ZonedDateTime zdt = ZonedDateTime.now();
// 指定时区构建
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

白话:完整时间,既有年月日时分秒,又绑定时区

比如:2026‑08‑19 18:00:00 +08:00[Asia/Shanghai],明确这是北京时间。

常用方法

① 转其他对象

方法 返回值 说明
LocalDateTime toLocalDateTime() LocalDateTime 丢掉时区,只保留本地年月日时分秒
Instant toInstant() Instant 剥离时区,转为 UTC 时间戳 Instant
LocalDate toLocalDate() LocalDate 只拿年月日
LocalTime toLocalTime() LocalTime 只拿时分秒

② 时间加减(返回新对象,原对象不变)

方法 作用
plusDays(long days) 加几天
minusMonths(long months) 减几个月
withXxx (long days) 修改时间系列的方法

③ 时间比较

方法 作用
isBefore(ZonedDateTime other) 是否早于另一个时间
isAfter(ZonedDateTime other) 是否晚于另一个时间
复制代码
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.systemDefault());
Instant instant = zdt.toInstant();
LocalDateTime ldt = zdt.toLocalDateTime();

LocalDateTime 转 ZonedDateTime

复制代码
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());

案例

java 复制代码
public static void main(String[] args) {
    //1.获得当前时间的ZoneDateTime对象(带时区)
    ZonedDateTime now = ZonedDateTime.now();
    System.out.println(now);//2026-01-23T14:36:48.289692100+08:00[Asia/Shanghai]
    //2.获得指定时间的ZoneDatetime对象(带时区)
    //按年月日时分秒纳秒时区指定
    ZonedDateTime.of(2026,6,16,23,23,
            22,23, ZoneId.of("Asia/Shanghai"));
    //3.通过Instant+时区的方法获取指定事件对象
    Instant instant = Instant.ofEpochMilli(0l);
    ZoneId zoneId = ZoneId.of("Asia/Shanghai");
    System.out.println(ZonedDateTime.ofInstant(instant, zoneId));//1970-01-01T08:00+08:00[Asia/Shanghai]
   //4.withXxx 修改时间系列的方法
    ZonedDateTime zonedDateTime = now.withYear(2000);
    System.out.println(zonedDateTime);//2000-01-23T14:48:58.668346200+08:00[Asia/Shanghai]
    //减少时间系列的方法
    ZonedDateTime zonedDateTime1 = zonedDateTime.minusDays(1);
    System.out.println(zonedDateTime1);//2000-01-22T14:54:56.174043700+08:00[Asia/Shanghai]
    //增加时间系列的方法
    ZonedDateTime zonedDateTime2 = zonedDateTime.plusDays(1);
    System.out.println(zonedDateTime2);//2000-01-24T14:54:56.174043700+08:00[Asia/Shanghai]
}
/*jdk8出现的时间对象都是不可改变的
如果我们修改 增加或者减少
调用者是不会发生改变的 只会产生新的时间对象
 */

笔记重点总结

  1. 这三个类全部不能 new,全部用静态方法创建对象
  2. ZoneId:只存时区,没有时间;systemDefault()拿系统时区
  3. Instant:UTC 时间戳,桥梁;atZone(zoneId)套上时区得到 ZonedDateTime
  4. ZonedDateTime = 本地时间 + 时区;可以转 Instant、LocalDateTime、LocalDate、LocalTime
  5. LocalDateTime没有时区,不能直接转 Instant,必须先 atZone () 变成 ZonedDateTime

转换速记

java 复制代码
Instant --atZone(zoneId)--> ZonedDateTime --toLocalDateTime()--> LocalDateTime

LocalDateTime --atZone(zoneId)--> ZonedDateTime --toInstant()--> Instant

4. LocalDate (只有:年‑月‑日,没有时分秒)

1.1创建对象(静态方法)

方法 说明
LocalDate.now() 获取系统当前的年月日
LocalDate.of(int year,int month,int dayOfMonth) 指定年月日构建对象

1.2常用获取方法

方法 作用
int getYear() 获取年
int getMonthValue() 获取月份(1‑12,没有 0 坑!
int getDayOfMonth() 获取当月几号
int getDayOfYear() 获取一年中的第几天
DayOfWeek getDayOfWeek() 获取星期

1.3时间加减(返回新对象)

方法 作用
plusDays(long n) 加 n 天
plusMonths(long n) 加 n 月
minusDays(long n) 减 n 天
minusYears(long n) 减 n 年

1.4比较

方法 作用
isBefore(LocalDate other) 是否在另一个日期之前
isAfter(LocalDate other) 是否在另一个日期之后
isEqual(LocalDate other) 日期是否相等

示例

Java 复制代码
LocalDate date = LocalDate.of(2023,11,11);
System.out.println(date.getMonthValue()); //11

案例

Java 复制代码
public static void main(String[] args) {
    //当前时间的日历对象  包括年月日
    LocalDate localDate = LocalDate.now();
    System.out.println(localDate);
    //获得指定时间的日历对象
    LocalDate localDate1 = LocalDate.of(2024,4,2);
    System.out.println(localDate1);

    System.out.println("==========================");

    //get方法获取日历中每个属性的值
    //年
    int year   = localDate.getYear();
    System.out.println(year);//2026
    //月: 第一种形式
    int month = localDate.getMonthValue();
    System.out.println(month);//1
    // 第二种形式
    Month month1 = localDate.getMonth();
    System.out.println(month1.getValue());//1
    //日
    int day = localDate.getDayOfMonth();
    System.out.println(day);//23
    //周
    DayOfWeek dayOfWeek = localDate1.getDayOfWeek();
    System.out.println(dayOfWeek); //TUESDAY
    System.out.println(dayOfWeek.getValue());//2

    System.out.println("==========================");

    //is开头的方法表示判断
    boolean after = localDate.isAfter(localDate);
    System.out.println(after);//false
    boolean after1 = localDate1.isAfter(localDate);
    System.out.println(after1);//false

    System.out.println("==========================");

    //with开头的表示修改方法 只能修改年月日
    LocalDate localDate2 = localDate1.withYear(2000);
    System.out.println(localDate2);//2000-04-02

    System.out.println("==========================");

    //minus开头的方法表示减少,只能减少年月日
    LocalDate localDate3 = localDate.minusYears(1);
    System.out.println(localDate3);//2025-01-23
    //plus开头的方法表示增加,只能增加年月日
    LocalDate localDate4 = localDate.plusYears(1);
    System.out.println(localDate4);//2027-01-23

    System.out.println("==========================");

    //判断今天是不是你生日
    LocalDate bir = LocalDate.of(2026, 1, 12);
    Month today = Month.from(LocalDate.now());
    System.out.println("今天是你的生日吗"+today.equals(bir));

}

5. LocalTime(只有:时‑分‑秒,没有年月日)

2.1创建对象

方法 说明
LocalTime.now() 获取当前时分秒
LocalTime.of(int hour,int minute,int second) 指定时分秒构建

2.2常用获取

方法 作用
int getHour() 小时 (24 小时制)
int getMinute() 分钟
int getSecond()

2.3加减、比较

plusHours()minusMinutes()isBefore()isAfter()

java 复制代码
LocalTime time = LocalTime.of(0,1,0);

案例

Java 复制代码
public static void main(String[] args) {
    // 获取当前日历对象 包括时分秒
    LocalTime now = LocalTime.now();
    System.out.println("今天的时间"+now);

    int hour = now.getHour();//时
    System.out.println(hour);
    int minute = now.getMinute();//分
    System.out.println(minute);
    int second = now.getSecond();//秒
    System.out.println(second);
    int nano = now.getNano();//纳秒
    System.out.println(nano);

    System.out.println("==========================");
    System.out.println(LocalTime.of(11, 12));
    System.out.println(LocalTime.of(11, 12, 30));
    System.out.println(LocalTime.of(11, 12, 30,2000));
    LocalTime localTime = LocalTime.of(11, 12, 30,2000);

    System.out.println("==========================");
    //is系列的方法
    System.out.println(localTime.isBefore(now));//true
    System.out.println(localTime.isAfter(now));//false

    //with系列的方法 只能修改时分秒
    System.out.println( now.withHour(2));//02:31:08.892886700

    //minus系列的方法 只能减少时分秒
    System.out.println(now.minusHours(2));//15:31:08.892886700
    //plus系列的方法,只能增加时分秒
    System.out.println(now.plusHours(2));//19:31:08.892886700

6. LocalDateTime(年月日 + 时分秒,最常用,不带时区

3.1创建对象

方法 说明
LocalDateTime.now() 获取当前完整本地时间
LocalDateTime.of(int y,int m,int d,int h,int mi,int s) 指定年月日时分秒创建
LocalDateTime.of(LocalDate date,LocalTime time) 传入 LocalDate+LocalTime 组合生成

3.2获取组件

方法 返回值 作用
toLocalDate() LocalDate 提取年月日部分
toLocalTime() LocalTime 提取时分秒部分
getYear() int
getMonthValue() int 月 (1‑12)
getDayOfMonth() int
getHour() int 小时
getMinute() int 分钟

3.3时间加减(返回新对象,原对象不变)

Java 复制代码
plusDays()  plusMonths() plusHours()
minusDays() minusMonths() minusHours()

3.4比较

isBefore()isAfter()

⚠️重要:加上时区转为 ZonedDateTime

LocalDateTime 本身没有时区,不能直接转 Instant

Java 复制代码
// LocalDateTime + 时区 → ZonedDateTime
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());

格式化解析(搭配 DateTimeFormatter)

java 复制代码
//格式化:对象→字符串
String str = ldt.format(DateTimeFormatter.ofPattern("yyyy‑MM‑dd HH:mm:ss"));
//解析:字符串→对象
LocalDateTime ldt2 = LocalDateTime.parse(str,DateTimeFormatter.ofPattern("yyyy‑MM‑dd HH:mm:ss"));

案例

Java 复制代码
public static void main(String[] args) {
    //当前时间的日历对象 包括年月日时分秒
    LocalDateTime localDateTime = LocalDateTime.now();
    System.out.println("今天是"+localDateTime);//今天是2026-01-23T16:17:35.229178800
    System.out.println(localDateTime.getYear());//年 2026
    System.out.println(localDateTime.getMonthValue());//月 1
    System.out.println(localDateTime.getDayOfMonth());//日23
    System.out.println(localDateTime.getHour());//时 16

    System.out.println("==========================");

    //日:当年的第几天
    System.out.println(localDateTime.getDayOfYear());
    //月:
    Month month = localDateTime.getMonth();
    System.out.println(month.getValue());//1
    //星期:
    DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
    System.out.println(dayOfWeek.getValue());//5

    System.out.println("==========================");

    //转换为LocalData对象
    LocalDate ld = localDateTime.toLocalDate();
    System.out.println(ld);//2026-01-23
    //转换为LocalTime对象
    LocalTime lt = localDateTime.toLocalTime();
    System.out.println(lt);//16:36:03.871771300
    System.out.println(lt.getHour());//16
    System.out.println(lt.getMinute());//36
    System.out.println(lt.getSecond()); //3
5.2.2 格式化类 DateTimeFormatter

DateTimeFormatter

包:java.time.format.DateTimeFormatterJava8 新版格式化工具,线程安全!替代 SimpleDateFormat

不可变类,不能 new,通过静态方法创建实例

1.创建对象(静态方法)

方法 说明
DateTimeFormatter.ofPattern("yyyy‑MM‑dd HH:mm:ss") 自定义格式模板,最常用

模式符号和老的SimpleDateFormat一样

  • yyyy 4 位年
  • MM 月份 (01‑12)
  • dd 日期
  • HH 24 小时小时
  • mm 分钟
  • ss

2.两大核心功能

1. 格式化:时间对象 → 字符串 format ()

LocalDate / LocalTime / LocalDateTime / ZonedDateTime 都有 .format(格式化器) 方法

java 复制代码
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy‑MM‑dd HH:mm:ss");
String timeStr = ldt.format(fmt); 

2. 解析:字符串 → 时间对象 parse ()

时间类的静态 parse 方法,传入字符串 + formatter

java 复制代码
String s = "2023‑11‑11 00:01:00";
LocalDateTime ldt = LocalDateTime.parse(s, fmt);

和旧 SimpleDateFormat 对比

SimpleDateFormat DateTimeFormatter
所属包 java.text java.time.format
线程安全 ❌不安全,不能共享 ✅线程安全,可以全局共用
创建方式 new 对象 静态ofPattern()
格式化 sdf.format(date) ldt.format(formatter)
解析 sdf.parse(str) LocalDateTime.parse(str,formatter)

⚠️注意点

  1. 没有抛出受检异常 ParseException!

    SimpleDateFormat#parse需要throws ParseException

    新版parse如果格式错误,抛出DateTimeParseException(运行时异常,不用写 throws 声明)。

  2. 不能直接格式化 Date 对象

    DateTimeFormatter 是给 java.time 新时间类用的。

    如果是老 Date:先转成 Instant→ZonedDateTime,再格式化。

java 复制代码
Date date = new Date();
ZonedDateTime zdt = date.toInstant().atZone(ZoneId.systemDefault());
String str = zdt.format(fmt);

完整示例代码

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

public class TestFormat {
    public static void main(String[] args) {
        //1.创建格式化器
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy‑MM‑dd HH:mm:ss");

        //格式化:对象→字符串
        LocalDateTime now = LocalDateTime.now();
        String s1 = now.format(fmt);
        System.out.println(s1);

        //解析:字符串→LocalDateTime对象
        String timeText = "2023‑11‑11 00:10:00";
        LocalDateTime parseTime = LocalDateTime.parse(timeText, fmt);
        System.out.println(parseTime);
    }
}

笔记总结

  1. DateTimeFormatter.ofPattern("格式") 创建实例
  2. 对象.format (formatter):时间对象转字符串
  3. LocalDateTime.parse(字符串,formatter):字符串解析成时间对象
  4. 线程安全,项目优先用,不要用 SimpleDateFormat
  5. 只服务 java.time 新类;老 Date 要先转换成 ZonedDateTime 再使用。
5.2.3 时间间隔工具类

包:java.time用来计算时间间隔、时间差,配合 java.time 新时间类使用

1. Duration (时分秒:时间间隔,处理秒、毫秒)

适合:LocalTime、LocalDateTime、Instant;处理时分秒级别的时间差

不处理年月日!

1.1创建对象

方法 作用
Duration.between(开始,结束) 计算两个时间之间的间隔
Duration.ofHours(2) 直接构建 2 小时间隔
Duration.ofMinutes(30) 构建 30 分钟间隔

1.2常用方法

方法 作用
long toHours() 把间隔转成总小时数
long toMinutes() 转总分钟
long toSeconds() 转总秒
long toMillis() 转总毫秒
plusHours(1) 间隔加 1 小时
minusMinutes(5) 间隔减 5 分钟

示例:

java 复制代码
LocalDateTime t1 = LocalDateTime.of(2023,11,11,0,1,0);
LocalDateTime t2 = LocalDateTime.of(2023,11,11,0,10,0);

Duration duration = Duration.between(t1,t2);
System.out.println(duration.toMinutes()); //9分钟

⚠️ 如果传入 LocalDate(只有年月日)会报错!Duration 只认带时分秒的对象。

案例

java 复制代码
public static void main(String[] args) {
    LocalDate now = LocalDate.now();
    System.out.println(now);//2026-01-24

    LocalDate birthday = LocalDate.of(2001,1,1);
    System.out.println(birthday);//2001-01-01

   Period period = Period.between(birthday,now);
    System.out.println("相差的时间间隔Period is " + period);//相差的时间间隔Period is P25Y23D
   System.out.println(period.getYears());//25
   System.out.println(period.getMonths());//0
   System.out.println(period.getDays());//23
    System.out.println(period.toTotalMonths());//300

2. Period(年月日间隔,只处理年、月、日)

专门给 LocalDate 使用,只算年、月、日,忽略时分秒

2.1创建对象

方法 作用
Period.between(LocalDate start,LocalDate end) 计算两个日期相差几年几月几日
Period.ofYears(1) 构建 1 年间隔
Period.ofMonths(2) 构建 2 个月间隔
Period.ofDays(10) 构建 10 天间隔

2.2常用方法

方法 作用
int getYears() 获取间隔几年
int getMonths() 获取间隔几个月
int getDays() 获取间隔几天

示例

java 复制代码
LocalDate d1 = LocalDate.of(2023,1,1);
LocalDate d2 = LocalDate.of(2025,3,5);
Period period = Period.between(d1,d2);
System.out.println(period.getYears());  //2
System.out.println(period.getMonths()); //2
System.out.println(period.getDays());  //4

⚠️只接收 LocalDate!传入 LocalDateTime 会自动剥离时分秒。

案例

java 复制代码
//用于计算两个时间间隔(秒,纳秒)
LocalTime time = LocalTime.now();
System.out.println(time);
LocalTime time1 = LocalTime.of(1,1,1);
System.out.println(time1);

Duration duration = Duration.between(time,time1);
System.out.println(duration);
System.out.println(duration.toDays());
System.out.println(duration.toHours());
System.out.println(duration.toMinutes());

3. ChronoUnit (工具枚举,最灵活,工作最常用)

枚举类,可以直接计算两个时间相差【指定单位】,天、小时、分钟、月、年都可以。

3.1常用常量

java 复制代码
ChronoUnit.YEARS    //年
ChronoUnit.MONTHS   //月
ChronoUnit.DAYS     //天
ChronoUnit.HOURS    //小时
ChronoUnit.MINUTES  //分钟
ChronoUnit.SECONDS  //秒

3.2核心方法 between(a,b)

java 复制代码
LocalDateTime l1 = LocalDateTime.of(2023,11,11,0,1,0);
LocalDateTime l2 = LocalDateTime.of(2023,11,11,2,5,0);

long day = ChronoUnit.DAYS.between(l1,l2);
long hour = ChronoUnit.HOURS.between(l1,l2);
long minute = ChronoUnit.MINUTES.between(l1,l2);

System.out.println(day);    //0
System.out.println(hour);   //2
System.out.println(minute); //124

3.3还可以给时间对象做加减:

java 复制代码
LocalDateTime ldt = LocalDateTime.now();
ldt.plus(3, ChronoUnit.DAYS); //加3天
ldt.minus(2, ChronoUnit.MONTHS); //减2个月

✅三者对比笔记(必背)

适用对象 处理粒度 特点
Duration LocalTime / LocalDateTime / Instant 时、分、秒、毫秒 不能处理年月日
Period LocalDate 年、月、日 不能处理时分秒
ChronoUnit LocalDate / LocalDateTime /ZonedDateTime/Instant 年 / 月 / 日 / 时 / 分 / 秒 万能,直接得到总数量,开发首选

重点区别举例

  • 2023‑01‑01 ~ 2023‑03‑05
    • Period:P2M4D → 2 个月零 4 天
    • ChronoUnit.DAYS.between:直接返回总天数 63

Period 是拆分成几年几月几日;ChronoUnit 直接返回换算后的总数值

坑点

  1. Duration 不要传 LocalDate,会抛异常。
  2. Period 只看年月日,时分秒直接丢弃。
  3. between(开始,结束)结束在开始前面,返回负数
java 复制代码
//结束时间 < 开始时间,得到负数
Duration.between(t2,t1).toMinutes(); // -9

案例'

Java 复制代码
LocalDateTime time =  LocalDateTime.now();
System.out.println(time);

LocalDateTime bir = LocalDateTime.of(2001, 6, 17, 6, 20, 20);
System.out.println(bir);
System.out.println("相差的年数为"+ChronoUnit.YEARS.between(bir,time));
System.out.println("相差的月数为"+ChronoUnit.MONTHS.between(bir,time));
System.out.println("相差的天数为"+ChronoUnit.DAYS.between(bir,time));
System.out.println("相差的小时数为"+ChronoUnit.HOURS.between(bir,time));
System.out.println("相差的分钟数为"+ChronoUnit.MINUTES.between(bir,time));
System.out.println("相差的秒数为"+ChronoUnit.SECONDS.between(bir,time));
System.out.println("相差的毫秒数为"+ChronoUnit.MILLIS.between(bir,time));
System.out.println("相差的纳秒数为"+ChronoUnit.NANOS.between(bir,time));
System.out.println("相差的半天数为"+ChronoUnit.HALF_DAYS.between(bir,time));
System.out.println("相差的十年数为"+ChronoUnit.DECADES.between(bir,time));
System.out.println("相差的周数为"+ChronoUnit.WEEKS.between(bir,time));
System.out.println("相差的世纪(百年)数为"+ChronoUnit.CENTURIES.between(bir,time));
System.out.println("相差的千年数为"+ChronoUnit.MILLENNIA.between(bir,time));
System.out.println("相差的纪元数为"+ChronoUnit.ERAS.between(bir,time));

一句话记忆

  1. Duration:算时分秒时间间隔
  2. Period:算年月日间隔(拆成年、月、日三部分)
  3. ChronoUnit:万能工具,直接拿相差总多少年 / 总多少天 / 总小时,实际开发用最多
  • LocalDate、LocalTime、LocalDateTime
  • Instant、ZoneId、ZonedDateTime
  • DateTimeFormatter
  • Duration、Period、ChronoUnit
相关推荐
DevOpenClub1 小时前
个人公开市场研究笔记功能需求文档
笔记
Rain的Java大神之路2 小时前
介绍一下分布式事务
java·分布式·后端·spring·spring cloud·架构·springcloud
吴声子夜歌3 小时前
Java面试题——基础(一)
java·开发语言
别动我齐刘海3 小时前
机器人运动控制学习2——基础进阶
c++·人工智能·神经网络·学习·目标检测·机器学习·机器人
南城以南溫暖如初1473 小时前
外卖CPS实战指南:从技术选型到运营落地全流程解析
java·spring boot·mysql·架构·vue
傻啦嘿哟4 小时前
英雄联盟皮肤爬虫:爬取全皮肤价格与特效,做比价工具
java·c++·爬虫
码匠许师傅5 小时前
【C++ 面试真题】24. 聊聊 C++ 的时间日期处理
java·c++·面试
0566465 小时前
agent学习——流式响应与文本切分
网络·python·学习
mqiqe5 小时前
AgentScope Java 2.0 Agent 状态存储(AgentStateStore)深度解析:构建可恢复、可扩展的智能体运行时
java·运维·网络