Java API

Math类

基本特性

  • 所在包:java.lang包(使用时无需手动导包)
  • 类结构:final class Mathfinal修饰,禁止继承)
  • 核心功能:提供执行基础数学运算的静态方法
  • 对象创建限制:API文档中无公开构造方法,禁止通过new Math()实例化对象

调用方式

无需实例化,所有字段和方法均为 static,直接通过 Math.字段名Math.方法名(参数列表) 调用。

示例:

java 复制代码
double pi = Math.PI;         // 获取圆周率
int max = Math.max(10, 20);  // 返回 20
double root = Math.sqrt(4);  // 返回 2.0

字段摘要

修饰符和类型 字段 描述
static final double E 自然对数的底数(约等于 2.718)
static final double PI 圆周率(约等于 3.14159)

方法摘要(常用)

修饰符和类型 方法签名 描述
static double abs(double a) 返回 double 值的绝对值
static float abs(float a) 返回 float 值的绝对值
static int abs(int a) 返回 int 值的绝对值
static long abs(long a) 返回 long 值的绝对值
static double ceil(double a) 向上取整(返回 ≥a 的最小整数)
static double floor(double a) 向下取整(返回 ≤a 的最大整数)
static int round(float a) 四舍五入(返回最接近的 int)
static long round(double a) 四舍五入(返回最接近的 long)
static double max(double a, double b) 返回两个 double 值的较大值
static float max(float a, float b) 返回两个 float 值的较大值
static int max(int a, int b) 返回两个 int 值的较大值
static long max(long a, long b) 返回两个 long 值的较大值
static double min(double a, double b) 返回两个 double 值的较小值
static int min(int a, int b) 返回两个 int 值的较小值
static double pow(double a, double b) 返回 a 的 b 次幂(a^b)
static double sqrt(double a) 返回 double 值的平方根
static double cbrt(double a) 返回 double 值的立方根
static double random() 返回 [0.0, 1.0) 的随机小数
static double sin(double a) 返回角度的正弦值(弧度制)
static double cos(double a) 返回角度的余弦值(弧度制)
static double tan(double a) 返回角度的正切值(弧度制)
static double toRadians(double angdeg) 将角度转换为弧度
static double toDegrees(double angrad) 将弧度转换为角度
static double log(double a) 返回自然对数(底数为 e)
static double log10(double a) 返回底数为 10 的对数
static double exp(double a) 返回 e 的 a 次幂(e^a)

System类

基本特性

  • 所在包:java.lang包(使用时无需手动导包)
  • 类结构:final class Systemfinal修饰,禁止继承)
  • 核心功能:提供与系统交互的实用方法和标准I/O流
  • 对象创建限制:API文档中无公开构造方法,禁止通过new System()实例化对象

调用方式

无需实例化,所有字段和方法均为 static,直接通过 System.字段名System.方法名(参数列表) 调用。

示例:

java 复制代码
long timestamp = System.currentTimeMillis();  // 获取当前时间戳
System.out.println("Error Message");          // 标准输出流打印
String os = System.getProperty("os.name");    // 获取操作系统名称

字段摘要

修饰符和类型 字段 描述
static final InputStream in 标准输入流(通常对应键盘输入)
static final PrintStream out 标准输出流(控制台输出)
static final PrintStream err 标准错误输出流(红色错误输出)

方法摘要(常用)

修饰符和类型 方法签名 描述
static long currentTimeMillis() 返回当前时间戳(毫秒,1970-01-01至今)
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 数组复制(高效)
static void exit(int status) 终止JVM(0正常退出,非0异常退出)
static void gc() 请求JVM执行垃圾回收(不保证立即执行)
static String getProperty(String key) 获取系统属性(os.name/user.dir/file.separator等)
static String getenv(String name) 获取环境变量值(PATH/HOME等)
static void setIn(InputStream in) 重定向标准输入流
static void setOut(PrintStream out) 重定向标准输出流
static void setErr(PrintStream err) 重定向标准错误流
static String lineSeparator() 获取系统换行符(Windows:"\r\n", Linux:"\n")

📌 注意事项

  • arraycopy() 需确保目标数组有足够空间(否则抛出 IndexOutOfBoundsException
  • exit() 会立即终止JVM(后续代码不执行)
  • gc() 仅为建议,JVM不保证立即执行回收

arraycopy方法 详解

java 复制代码
// 复制数据源数组中从[数据源数组起始索引]开始的[拷贝个数]个元素,粘贴到 [目的地数组]中的从[目的地数组起始索引]开始的位置
public static void arraycopy(数据源数组,数据源数组起始索引,目的地数组,目的地数组起始索引,拷贝个数)

int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56 } ; 

// 进行数组元素的copy:复制srcArray数组中从0索引开始的3个元素,粘贴到 desArray数组中的从1索引开始的位置
System.arraycopy(srcArray , 0 , desArray , 1 , 3);
// 进行数组元素的删除:删除数组中第3个元素(67),只需将 67 后面的其他元素依次向前进行移动即可 
System.arraycopy(srcArray , 3 , srcArray , 2 , 3);

底层细节:

  1. 如果数据源数组和目的地数组都是基本数据类型,那么两者的类型必须保持一致,否则会报错

  2. 在拷贝的时候需要考虑数组的长度,如果超出范围也会报错

  3. 如果数据源数组和目的地数组都是引用数据类型,那么子类类型可以赋值给父类类型
    代码示例:

    java 复制代码
    class Person {} // 父类
    class Student extends Person { // 子类
        //......
    }
    
    public class Main {
        public static void main(String[] args) {
            // 创建学生对象和数组
            Student s1 = new Student("zhangsan", 23);
            Student s2 = new Student("lisi", 24);
            Student s3 = new Student("wangwu", 25);
            Student[] arr1 = {s1, s2, s3};
    
            // 创建Person数组并复制引用
            Person[] arr2 = new Person[3];
            System.arraycopy(arr1, 0, arr2, 0, 3);
    
            // 输出结果
            System.out.println("arr2内容: ");
            for(Person p : arr2) {
                System.out.println(p);
            }
    
            // 修改共享对象
            s1.name = "张三";
            System.out.println("\n修改后arr2[0]: " + arr2[0]);
        }
    }

Runtime

基本特性

  • 所在包:java.lang包(使用时无需手动导包)
  • 类结构:final class Runtimefinal修饰,禁止继承)
  • 核心功能:提供程序运行时环境的管理能力(内存监控、进程执行、JVM终止等)
  • 对象创建限制:
    • 禁止通过new Runtime()实例化对象
    • 只能通过静态方法 Runtime.getRuntime() 获取唯一实例(每个Java应用有且只有一个Runtime实例)

调用方式

  1. 获取实例:通过静态方法获取Runtime对象

    java 复制代码
    Runtime runtime = Runtime.getRuntime();
  2. 方法调用:通过Runtime实例调用非静态方法:[Runtime对象].方法名(参数列表)
    示例:

    java 复制代码
    long freeMem = runtime.freeMemory();       // 获取空闲内存
    runtime.exec("notepad.exe");               // 启动记事本
    int cores = runtime.availableProcessors(); // 获取处理器核心数

方法摘要(常用)

方法签名 描述
static Runtime getRuntime() 返回当前应用的Runtime对象
void exit(int status) 终止当前JVM(0正常退出,非0异常退出)
long totalMemory() 返回JVM当前管理的总内存量(字节)
long freeMemory() 返回JVM空闲内存量(字节)
long maxMemory() 返回JVM可申请的最大内存量(字节)
Process exec(String command) 执行cmd命令,返回Process对象(需处理IOException
void gc() 建议JVM执行垃圾回收(不保证立即执行)
int availableProcessors() 返回JVM可用处理器核心数
void addShutdownHook(Thread hook) 注册JVM关闭时的钩子线程(安全释放资源)
void load(String filename) 加载指定文件名的本地库
void loadLibrary(String libname) 加载系统库路径下的指定名称本地库

注意事项

  • exec()方法执行系统命令存在安全风险,需谨慎使用
  • 调用exit()会立即终止JVM,后续代码不会执行
  • 内存监控数据单位为字节,需手动转换(1MB = 1024*1024字节)
  • 本地库加载(load()/loadLibrary())需确保库文件存在且兼容当前系统

Object类

基本特性

  • 所在包:java.lang包(自动导入,无需手动导包)
  • 类层次地位:Java类层次结构的根超类(所有类都直接或间接继承Object)
  • 核心功能:提供对象基础操作(对象比较、字符串表示、线程同步等)
  • 对象创建限制:
    • 可通过new Object()创建实例
    • 但实际开发中很少直接创建Object对象

继承特性说明

  • 类继承:所有Java类默认继承Object类;自定义类未显式extends时,编译器自动添加extends Objectclass Person {} 等价于 class Person extends Object {}
  • 方法继承:父类(Object类)定义的方法会被所有子类继承;子类可重写其中关键方法(如toString()equals()

总结起来就是:由于类继承,所以在所有创建的Java类中都可以重写Object类定义的方法。

调用方式

通过任意Java对象调用继承自Object的方法: [任意对象].方法名(参数列表)

示例:

java 复制代码
Person p = new Person("Alice", 30);

// 调用toString()方法
String info = p.toString();  // 返回对象字符串表示

// 调用equals()方法
boolean same = p.equals(new Person("Alice", 30));  // 比较对象内容

// 调用getClass()方法
Class<?> cls = p.getClass();  // 获取对象运行时类

方法摘要(常用)

toString()核心作用:

  • 默认返回对象内存地址的字符串表示(类名@十六进制哈希值)
  • 重写后可返回对象的属性信息,便于调试和日志输出
  • 直接打印对象时自动隐式调用:System.out.println(obj) 实际上执行的是 System.out.println(obj.toString())

equals()核心作用:

  • 默认比较对象地址是否相同(与==行为一致)
  • 重写后可实现自定义对象内容比较(如比较属性值)

clone()核心作用

  • 创建对象的副本(需实现Cloneable接口)
  • 注意深浅拷贝问题
  • 必须满足以下两个条件才能成功调用
    1. 实现 Cloneable 接口:类必须声明实现该接口
    2. 重写 clone() 方法:访问权限改为 public

常见方法演示

演示toString方法

为了得到更有意义的输出(即对象的成员变量信息),我们需要在类中重写toString()方法。通过idea开发工具进行实现,具体步骤如下所示:

  1. 在空白处使用快捷键:alt + insert。此时会弹出如下的对话框\

  2. 选择toString,此时会弹出如下的对话框\

  3. 同时选择name和age属性,点击OK。此时IDEA自动生成toString方法的重写,代码如下所示:

    java 复制代码
    public class Student {
        private String name;  // 姓名
        private String age;   // 年龄
    
        // 构造方法
        public Student(String name, String age) {
            this.name = name;
            this.age = age;
        }
    
        // 使用IDEA自动生成toString()
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age='" + age + '\'' +
                    '}';
        }
    }
  4. 测试验证

    java 复制代码
    public class ObjectDemo01 {
        public static void main(String[] args) {
            // 创建学生对象
            Student s1 = new Student("itheima", "14");
    
            // 直接输出对象(自动调用toString())
            System.out.println(s1);
        }
    }

    运行程序进行测试,控制台输出结果如下所示:

    java 复制代码
    Student{name='itheima', age='14'}

输出结果与IDEA自动生成toString方法的重写的输出结果一致。证明直接输出一个对象,那么会默认调用对象的toString方法。

演示equals方法

为了得到更有意义的输出(即比较对象的属性),我们需要在类中重写equals方法。通过idea开发工具进行实现,具体步骤如下所示:

  1. 在空白处使用快捷键:alt + insert。此时会弹出如下的对话框\

  2. 选择equals() and hashCode()方法,弹出如下的对话框

    点击next,弹出如下对话框:\

    选择neme和age属性点击next,弹出如下对话框:\

    取消勾选name和age属性(因为此时窗口选择的是在生成hashCode方法时所涉及到的属性,关于hashCode方法后期再做重点介绍),点击Finish完成生成操作。此时IDEA自动生成equals方法和hashCode方法的重写,代码如下所示:

    java 复制代码
    @Override
    public boolean equals(Object o) {
        // 1. 自反性检查:如果是同一个对象(内存地址相同)
        if (this == o) return true;
    
        // 2. 安全性检查:排除null和非同类对象
        if (o == null || getClass() != o.getClass()) return false;
    
        // 3. 类型转换:将Object转为具体类型
        Student student = (Student) o;
    
        // 4. 关键属性比较:使用null安全的Objects.equals()
        return Objects.equals(name, student.name) && 
               Objects.equals(age, student.age);
    }
    @Override
    public int hashCode() {  // hashCode方法暂时使用不到,可以将hashCode方法删除
        return 0;
    }
  3. 测试验证

    java 复制代码
    public class ObjectDemo02 {
        public static void main(String[] args) {
            // 创建两个学生对象
            Student s1 = new Student("itheima" , "14") ;
            Student s2 = new Student("itheima" , "14") ;
            // 比较两个对象是否相等
            System.out.println(s1.equals(s2));
        }

    重写完毕以后运行程序进行测试,控制台输出结果如下所示:

    java 复制代码
    true

    此时equals方法比较的是对象的成员变量值,而s1和s2两个对象的成员变量值都是相同的。因此比较完毕以后的结果就是true。

演示clone方法

把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制

  • 对象克隆的分类: 深克隆和浅克隆
  • Object类默认的是浅克隆

浅克隆:

  • 对 对象内部的基本数据类型与引用数据类型的属性都进行拷贝
  • 基本数据类型拷贝过来的是具体的数据,引用数据类型拷贝过来的是地址值

深克隆: 拷贝基本数据类型;字符串复用;对引用数据类型进行重新创建

图示说明:

graph TD A[对象克隆] --> B[浅克隆] A --> C[深克隆] B --> D[拷贝基本类型值] B --> E[拷贝引用地址] C --> F[拷贝基本类型值] C --> G[创建新引用对象] C --> H[字符串复用]

对象深克隆实现代码

创建对象u1的一个副本(克隆),并将这个副本赋值给变量u2
User u2 = (User) u1.clone();

  • (User):clone() 返回的是 Object 类型(所有类的基类),但实际需要返回 User 类型的对象,需要进行显式类型转换

测试类 ObjectDemo4.java

java 复制代码
package com.itheima.a04objectdemo;

public class ObjectDemo4 {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 1. 创建原始对象
        int[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};
        User u1 = new User(1, "zhangsan", "1234qwer", "girl11", data);

        // 2. 克隆对象
        User u2 = (User) u1.clone();

        // 3. 验证克隆效果
        // 修改原始对象的数组数据
        u1.getData()[0] = 100;
        
        // 打印两个对象
        System.out.println("原始对象: " + u1);
        System.out.println("克隆对象: " + u2);
    }
}

用户类 User.java

java 复制代码
package com.itheima.a04objectdemo;

import java.util.StringJoiner;

// 实现Cloneable标记接口(无方法,仅表示可克隆)
public class User implements Cloneable {
    private int id;
    private String username;
    private String password;
    private String path;
    private int[] data;

    // 构造方法
    public User(int id, String username, String password, String path, int[] data) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.path = path;
        this.data = data;
    }

    // getter/setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public String getPath() { return path; }
    public void setPath(String path) { this.path = path; }
    public int[] getData() { return data; }
    public void setData(int[] data) { this.data = data; }

    // toString方法
    @Override
    public String toString() {
        return "User{id=" + id + 
               ", username='" + username + '\'' + 
               ", password='" + password + '\'' + 
               ", path='" + path + '\'' + 
               ", data=" + arrToString() + '}';
    }

    // 数组转字符串辅助方法
    private String arrToString() {
        StringJoiner sj = new StringJoiner(", ", "[", "]");
        for (int value : data) {
            sj.add(String.valueOf(value));
        }
        return sj.toString();
    }

    // 重写clone方法实现深克隆
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 1. 调用父类浅克隆方法,父类:在这里就是 `Object` 类。
        User clonedUser = (User) super.clone();
        
        // 2. 深克隆处理:复制数组内容
        
        //2.1 获取当前被克隆对象的数组引用 保存到 临时变量 originalData 中
        int[] originalData = this.data;  //data是前面定义的数组变量
        //2.2 创建一个与原数组的长度相同的新数组对象,作为受粘贴对象
        int[] newData = new int[originalData.length];  //originalData.length:原数组的长度
        //2.3 将原数组的每个元素值复制到新数组
        System.arraycopy(originalData, 0, newData, 0, originalData.length);
        
        // 3. 替换受粘贴对象的数组引用,将受粘贴对象的data引用指向新创建的数组clonedUser
        clonedUser.data = newData;
        
        return clonedUser;
    }
}

执行结果:

ini 复制代码
原始对象: User{id=1, username='zhangsan', password='1234qwer', path='girl11', data=[100, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0]}
克隆对象: User{id=1, username='zhangsan', password='1234qwer', path='girl11', data=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0]}

克隆关键点说明

完整深克隆实现要素

类别 要素 说明
基础要素 1. 实现 Cloneable 接口 标记可克隆
2. 重写 clone() 方法 提供访问入口
3. 调用 super.clone() 创建基础副本
深克隆扩展 4. 识别可变引用字段 如数组/集合/自定义对象
5. 创建字段新实例 newclone()
6. 复制字段内容 值复制/递归克隆
7. 更新克隆对象引用 指向新实例

浅克隆只需基础三要素

在上述代码中的具体体现

java 复制代码
// === 基础三要素 ===
public class User implements Cloneable {       // 要素1: 实现接口
    @Override                                 // 要素2: 重写方法
    protected Object clone() {
        User cloned = (User) super.clone();   // 要素3: 调用super.clone()
        
        // === 深克隆扩展 ===
        // 要素4: 识别可变字段 (data数组)
        // 要素5: 创建新实例
        int[] newData = new int[this.data.length]; 
        
        // 要素6: 复制内容
        System.arraycopy(this.data, 0, newData, 0, this.data.length);
        
        // 要素7: 更新引用
        cloned.data = newData;
        
        return cloned;
    }
}

特殊引用类型处理差异:

引用类型 处理方式
String 无需处理(不可变)
基本类型数组 System.arraycopy()Arrays.copyOf()
对象数组 循环 + 递归克隆
集合类 创建新集合并复制元素

关键结论

Java原生克隆机制(clone()方法)默认是浅克隆,要实现真正的对象隔离必须通过重写clone()方法实现深克隆。深克隆的核心在于为每个引用类型属性创建独立副本,尤其当对象包含嵌套结构时需递归处理。实际开发中推荐使用序列化或JSON工具库实现深克隆。

Objects类

基本特性

  • 所在包:java.util包(使用时需要手动导包)
  • 类结构:final class Objectsfinal修饰,禁止继承)
  • 核心功能:提供对象操作的工具方法(如判空、判等、哈希值计算等)
  • 对象创建限制:API文档中无公开构造方法,禁止通过new Objects()实例化对象

调用方式

无需实例化,所有方法均为 static,直接通过 Objects.方法名(参数列表) 调用。

示例:

java 复制代码
boolean equal = Objects.equals(obj1, obj2);  // 安全比较对象相等
boolean isNull = Objects.isNull(obj);        // 判断对象是否为null
int hash = Objects.hash(name, age, id);      // 生成对象哈希值

常见方法

基本对象操作

  1. public static String toString(Object obj):安全获取对象的字符串表示形式

    • 当对象不为null时,返回o.toString()的结果
    • 当对象为null时,返回字符串"null"

    优势 :避免直接调用toString()可能引发的NullPointerException

  2. public static boolean equals(Object a, Object b):安全比较两个对象是否相等

    • 如果两个对象都为null,返回true
    • 如果只有一个对象为null,返回false
    • 如果两个对象都不为null,返回a.equals(b)的结果 优势 :安全处理null值比较,避免NullPointerException
  3. public static boolean isNull(Object obj) :判断对象是否为null(等价于obj == null

  4. public static boolean nonNull(Object obj) :判断对象是否不为null(等价于obj != null

非空校验与默认值

  1. public static <T> T requireNonNull(Object obj):强制校验对象非空

    • 当对象不为null时,返回对象本身
    • 当对象为null时,抛出NullPointerException
  2. public static <T> T requireNonNull(Object obj, String message):带自定义错误信息的非空校验

    • 对象不为null时返回对象本身
    • 对象为null时抛出带指定消息的NullPointerException
  3. public static <T> T requireNonNullElse(Object obj, Object defaultObj):非空校验并提供默认值

    • 对象不为null时返回对象本身
    • 对象为null时返回指定的默认对象
  • 约束 :默认对象不能为null(否则抛出NullPointerException
  1. public static <T> T requireNonNullElseGet(Object obj, Supplier supplier) :非空校验并通过Supplier提供默认值
    • 对象不为null时返回对象本身
    • 对象为null时调用Supplier生成默认值
  • Supplier 是一个函数式接口 ,它代表一个无参数但有返回值的操作。通常通过 Lambda 表达式编写 Supplier
  • 约束 :Supplier不能为null(否则抛出NullPointerException

方法特性总结

说明:

  1. 泛型说明:方法签名中的<T>表示泛型类型,可接受任意非基本类型(引用类型)。在调用时,编译器会自动推断类型。
  2. requireNonNull系列方法常用于参数校验,确保传入的对象不为null
  3. requireNonNullElserequireNonNullElseGet提供安全的默认值机制,避免空指针。

案例演示

接下来我们就来通过一些案例演示一下Objects类中的这些方法特点。

案例1:演示重点学习方法

实现步骤:

  1. 创建一个学生类,提供两个成员变量(name , age);并且提供对应的无参构造方法和有参构造方法以及get/set方法,并且重写toString方法和equals方法
  2. 创建一个测试类(ObjectsDemo01), 在该类中编写测试代码

如下所示:

Student类

java 复制代码
public class Student {
    private String name ;       // 姓名
    private String age ;        // 年龄
    // 其他代码略
    ...
}

ObjectsDemo01测试类

java 复制代码
public class ObjectsDemo01 {
    public static void main(String[] args) {
        // 调用方法
        method_04() ;
    }

    // 测试nonNull方法
    public static void method_04() {
        // 创建一个学生对象
        Student s1 = new Student("itheima" , "14") ;
        // 调用Objects类中的nonNull方法
        boolean result = Objects.nonNull(s1);
        // 输出结果
        System.out.println(result); // 输出: true (因为s1不是null)
    }

    // 测试isNull方法
    public static void method_03() {
        // 创建一个学生对象
        Student s1 = new Student("itheima" , "14") ;
        // 调用Objects类中的isNull方法
        boolean result = Objects.isNull(s1);
        // 输出结果
        System.out.println(result); // 输出: false (因为s1不是null)
    }

    // 测试equals方法
    public static void method_02() {
        // 创建两个学生对象
        Student s1 = new Student("itheima" , "14") ;
        Student s2 = new Student("itheima" , "14") ;
        // 调用Objects类中的equals方法,比较两个对象是否相等
        boolean result = Objects.equals(s1, s2);     // 如果Student没有重写Object类中的equals方法,此处比较的还是对象的地址值
        // 输出结果
        System.out.println(result); // 输出: false (除非Student类重写了equals方法,否则比较的是内存地址)
    }

    // 测试toString方法
    public static void method_01() {
        // 创建一个学生对象
        Student s1 = new Student("itheima" , "14") ;
        // 调用Objects中的toString方法,获取s1对象的字符串表现形式
        String result = Objects.toString(s1);       // 如果Student没有重写Object类中的toString方法,此处还是返回的对象的地址值
        // 输出结果
        System.out.println(result); // 输出: Student类的toString()结果或默认的对象哈希表示(如Student@1b6d3586)
    }
}

案例2:演示需要了解的方法

java 复制代码
public class ObjectsDemo02 {
    public static void main(String[] args) {
        // 调用方法
        method_03();
    }

    // 演示requireNonNullElseGet
    public static void method_03() {
        // 创建一个学生对象
        Student s1 = new Student("itheima" , "14") ;
        // 调用Objects对象的requireNonNullElseGet方法,该方法的第二个参数是Supplier类型的,查看源码我们发现Supplier是一个函数式接口,
        // 那么我们就可以为其传递一个Lambda表达式,而在Supplier接口中所定义的方法是无参有返回值的方法,因此具体调用所传入的Lambda表达式如下所示
        Student student = Objects.requireNonNullElseGet(s1, () -> {
            return new Student("itcast", "14");
        });
        // 输出
        System.out.println(student); // 输出: Student{name='itheima', age='14'} (因为s1不为null,直接返回s1)
    }

    // 演示requireNonNullElse
    public static void method_02() {
        // 创建一个学生对象
        Student s1 = new Student("itheima" , "14") ;
        // 调用Objects对象的requireNonNullElse方法
        Student student = Objects.requireNonNullElse(s1, new Student("itcast", "14"));
        // 输出
        System.out.println(student); // 输出: Student{name='itheima', age='14'} (因为s1不为null,直接返回s1)
    }

    // 演示requireNonNull
    public static void method_01() {
        // 创建一个学生对象
        Student s1 = new Student("itheima" , "14") ;
        // 调用Objects对象的requireNonNull方法
        Student student = Objects.requireNonNull(s1);
        // 输出
        System.out.println(student); // 输出: Student{name='itheima', age='14'} (因为s1不为null,直接返回s1)
    }
}

BigInteger类

基本特性

  • 所在包:java.math包(使用时需要手动导包)
  • 类结构:public class BigInteger extends Number implements Comparable<BigInteger>
  • 核心功能:表示不可变的任意精度的整数,提供所有Java的基本整数操作符的对应物,并提供java.lang.Math的所有相关方法
  • 数值范围:理论上可表示无限大的整数(仅受JVM内存限制)

调用方式

通过创建BigInteger对象实例来调用其方法。

示例:

java 复制代码
import java.math.BigInteger;

BigInteger bigInt = new BigInteger("123456789012345678901234567890");
BigInteger result = bigInt.add(anotherBigInt);  // 加法运算
int comparison = bigInt.compareTo(anotherBigInt); // 比较大小

常见方法

构造方法

java 复制代码
public BigInteger(int num, Random rnd)  // 生成随机大整数,范围:[0 ~ 2^num - 1]
public BigInteger(String val)           // 通过字符串创建指定的大整数
public BigInteger(String val, int radix) // 创建指定进制的大整数

静态工厂方法

java 复制代码
public static BigInteger valueOf(long val)  // 静态方法获取BigInteger对象(内部有优化)

成员方法

java 复制代码
// 算术运算方法
public BigInteger add(BigInteger val)                   // 加法运算
public BigInteger subtract(BigInteger val)              // 减法运算
public BigInteger multiply(BigInteger val)              // 乘法运算
public BigInteger divide(BigInteger val)                // 除法运算
public BigInteger[] divideAndRemainder(BigInteger val)  // 除法运算,返回商和余数数组
public BigInteger pow(int exponent)                     // 幂运算(次方)

// 比较方法
public boolean equals(Object x)                         // 相等比较
public BigInteger max(BigInteger val)                   // 返回较大值
public BigInteger min(BigInteger val)                   // 返回较小值

// 类型转换方法
public int intValue()                                   // 转换为int类型(可能丢失精度)

方法使用说明

  1. 对象创建
    • 如果数字未超出long类型范围,推荐使用静态方法valueOf()获取对象(性能更优)
    • 如果数字超出long类型范围,必须使用构造方法创建对象
    • BigInteger对象一旦创建,其内部值不可改变(不可变性)
  2. 运算特性
    • 所有算术运算都会产生新的BigInteger对象,原对象保持不变
    • 进行除法运算时,如果除数为0会抛出ArithmeticException
  3. 注意事项
    • 使用intValue()方法转换时,如果值超出int范围,结果可能不正确(数据截断)
    • 比较两个BigInteger对象时,应使用equals()方法而非==运算符

案例演示

演示1:BigInteger对象创建与方法演示

java 复制代码
import java.math.BigInteger;
import java.util.Random;

public class BigIntegerDemo1 {
    public static void main(String[] args) {
    
        // 1. 获取随机大整数 (范围: 0 ~ 2^4-1 = 0~15)
        Random r = new Random();
        for (int i = 0; i < 5; i++) {
            BigInteger bd1 = new BigInteger(4, r);
            System.out.println("随机数 " + (i+1) + ": " + bd1);
        }

        // 2. 获取指定的大整数
        // 注意: 字符串中必须是整数,否则会报错
        BigInteger bd2 = new BigInteger("12345678901234567890");
        System.out.println("指定大整数: " + bd2);
        
        // 3. 获取指定进制的大整数
        // 注意: 
        // 1. 字符串中的数字必须是整数
        // 2. 字符串中的数字必须要跟进制吻合
        BigInteger bd3 = new BigInteger("1010", 2); // 二进制表示的10
        System.out.println("二进制1010转换为十进制: " + bd3);
        
        // 4. 静态方法获取BigInteger对象
        // 注意:
        // 1. 能表示范围比较小,只能在long的取值范围之内
        // 2. 在内部对常用数字(-16~16)进行了优化
        BigInteger bd4 = BigInteger.valueOf(16);
        BigInteger bd5 = BigInteger.valueOf(16);
        System.out.println("值相同的对象是否相同: " + (bd4 == bd5)); // true (优化范围内)
        
        BigInteger bd6 = BigInteger.valueOf(17);
        BigInteger bd7 = BigInteger.valueOf(17);
        System.out.println("值相同的对象是否相同: " + (bd6 == bd7)); // false (超出优化范围)
        
        // 5. 对象不可变性演示
        BigInteger bd8 = BigInteger.valueOf(1);
        BigInteger bd9 = BigInteger.valueOf(2);
        // 不会修改原对象,而是产生新对象
        BigInteger result = bd8.add(bd9);
        System.out.println("加法结果: " + result);
        System.out.println("原对象bd8的值: " + bd8); // 保持不变
        System.out.println("原对象bd9的值: " + bd9); // 保持不变
    }
}

演示2:BigInteger常用运算方法演示

java 复制代码
import java.math.BigInteger;

public class BigIntegerDemo2 {
    public static void main(String[] args) {
        /*
            public BigInteger add(BigInteger val) 加法
            public BigInteger subtract(BigInteger val) 减法
            public BigInteger multiply(BigInteger val) 乘法
            public BigInteger divide(BigInteger val) 除法,获取商
            public BigInteger[] divideAndRemainder(BigInteger val) 除法,获取商和余数
            public boolean equals(Object x) 比较是否相同
            public BigInteger pow(int exponent) 次幂
            public BigInteger max/min(BigInteger val) 返回较大值/较小值
            public int intValue() 转为int类型整数,超出范围数据有误
        */

        // 创建两个BigInteger对象
        BigInteger bd1 = BigInteger.valueOf(20);
        BigInteger bd2 = BigInteger.valueOf(6);
        
        // 加法
        BigInteger sum = bd1.add(bd2);
        System.out.println("加法结果: " + sum);
        
        // 减法
        BigInteger difference = bd1.subtract(bd2);
        System.out.println("减法结果: " + difference);
        
        // 乘法
        BigInteger product = bd1.multiply(bd2);
        System.out.println("乘法结果: " + product);
        
        // 除法(获取商)
        BigInteger quotient = bd1.divide(bd2);
        System.out.println("除法商: " + quotient);
        
        // 除法(获取商和余数)
        BigInteger[] divResult = bd1.divideAndRemainder(bd2);
        System.out.println("商: " + divResult[0] + ", 余数: " + divResult[1]);
        
        // 相等比较
        boolean isEqual = bd1.equals(bd2);
        System.out.println("是否相等: " + isEqual);
        
        // 次幂
        BigInteger power = bd1.pow(3);
        System.out.println("20的3次方: " + power);
        
        // 最大值/最小值
        BigInteger max = bd1.max(bd2);
        BigInteger min = bd1.min(bd2);
        System.out.println("最大值: " + max + ", 最小值: " + min);
        
        // 转换为int类型(注意可能的数据丢失)
        BigInteger bigValue = BigInteger.valueOf(2147483647); // int最大值
        int intValue = bigValue.intValue();
        System.out.println("转换为int: " + intValue);
        
        // 转换为double类型
        double doubleValue = bigValue.doubleValue();
        System.out.println("转换为double: " + doubleValue);
    }
}

底层存储方式

BigInteger类的底层实现基于以下原理:

存储机制

  • 计算机底层存储的都是二进制数据(010101...),数据类型是编程语言层面的抽象概念
  • BigInteger将大整数转换为二进制后,每32个bit(4字节)为一组,存储在int类型的数组中

容量限制

  • 数组最大长度:理论上数组最多能存储约21亿个元素(受限于Java数组的最大长度,约为Integer.MAX_VALUE)
  • 每个元素的取值范围:数组中每个int元素可以表示0到2³²-1(约42亿多)的数值
  • 理论最大数值:基于上述限制,BigInteger能表示的最大数字理论上可达(2³²)^(2³¹) ≈ 42亿的21亿次方
  • 实际限制:在实际应用中,尚未达到理论最大值之前,计算机的内存就会先被耗尽。所以通常认为BigInteger可以表示"无限大"的整数(实际上受可用内存限制)

存储方式如图所示:

BigDecimal类

引入 浮点数(float/double)在进行数学运算时可能存在精度丢失问题。计算机底层使用二进制运算,十进制浮点数转换为二进制时可能产生无限循环二进制值,导致运算结果不精确。BigDecimal通过基于十进制的存储和运算机制,从根本上解决精度问题。

基本特性

  • 所在包:java.math包(使用时需手动导包)
  • 类结构:public class BigDecimal(非final修饰,可继承)
  • 核心功能:提供高精度的十进制运算,解决浮点数运算中的精度丢失问题
  • 对象创建:通过构造方法或静态方法实例化,支持从字符串、整数、双精度等类型创建对象

调用方式

需通过实例化对象调用其方法,提供多种算术运算和精度控制功能。

示例:

java 复制代码
BigDecimal num1 = new BigDecimal("0.1");      // 通过字符串构造
BigDecimal num2 = BigDecimal.valueOf(0.2);    // 静态工厂方法
BigDecimal result = num1.add(num2);           // 加法运算
System.out.println(result);                   // 输出: 0.3

常见方法

构造方法

BigDecimal类提供多种构造方法创建对象,其中最常用的构造方法包括:

java 复制代码
BigDecimal(String val)   // 通过字符串创建BigDecimal对象
BigDecimal(double val)   // 通过双精度浮点数创建BigDecimal对象
BigDecimal(int val)      // 通过整型数据创建BigDecimal对象

常用成员方法

BigDecimal类提供精确的算术运算方法,主要包括:

java 复制代码
public BigDecimal add(BigDecimal value)         // 加法运算
public BigDecimal subtract(BigDecimal value)    // 减法运算
public BigDecimal multiply(BigDecimal value)    // 乘法运算
public BigDecimal divide(BigDecimal value)      // 除法运算

案例演示

案例1:基本四则运算演示

通过BigDecimal类进行精确的数学运算,避免浮点数精度丢失问题:

java 复制代码
// 创建两个BigDecimal对象
BigDecimal b1 = new BigDecimal("0.3");
BigDecimal b2 = new BigDecimal("4");

// 进行四则运算并输出结果
System.out.println(b1.add(b2));         // 加法运算:4.3
System.out.println(b1.subtract(b2));    // 减法运算:-3.7
System.out.println(b1.multiply(b2));    // 乘法运算:1.2
System.out.println(b1.divide(b2));      // 除法运算:0.075

使用BigDecimal进行浮点数计算可完全避免精度损失问题,确保计算结果的准确性。

案例2:除法运算的特殊情况处理

当除法运算结果为无限循环小数时,直接调用divide方法会抛出ArithmeticException异常:

java 复制代码
BigDecimal b1 = new BigDecimal("1");
BigDecimal b2 = new BigDecimal("3");
System.out.println(b1.divide(b2));  // 抛出ArithmeticException

解决方案是使用重载的divide方法指定精度和舍入模式:

java 复制代码
BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

参数说明:

  • divisor:除数对应的BigDecimal对象
  • scale:精确位数(保留小数位数)
  • roundingMode:舍入模式,常用模式包括:
    • UP:直接进1
    • FLOOR:直接删除
    • HALF_UP:四舍五入

应用示例:

java 复制代码
// UP模式(直接进1)
BigDecimal b1 = new BigDecimal("1");
BigDecimal b2 = new BigDecimal("3");
System.out.println(b1.divide(b2, 2, RoundingMode.UP));  // 输出: 0.34

// FLOOR模式(直接删除)
System.out.println(b1.divide(b2, 2, RoundingMode.FLOOR));  // 输出: 0.33

// HALF_UP模式(四舍五入)
BigDecimal b3 = new BigDecimal("0.3");
BigDecimal b4 = new BigDecimal("4");
System.out.println(b3.divide(b4, 2, RoundingMode.HALF_UP));  // 输出: 0.08

实际开发中推荐使用可指定精度和舍入模式的divide方法进行除法运算,以确保程序的稳定性和准确性。

底层存储方式

把数据看成字符串,遍历得到里面的每一个字符,把这些字符在ASCII码表上的值,都存储到数组中。

相关推荐
Cisyam17 分钟前
使用Bright Data API轻松构建LinkedIn职位数据采集系统
后端
float_六七17 分钟前
Spring Boot 3为何强制要求Java 17?
java·spring boot·后端
bobz96531 分钟前
ovs arp
后端
_風箏43 分钟前
SpringBoot【集成ElasticSearch 01】2种方式的高级客户端 RestHighLevelClient 使用(依赖+配置+客户端API测试源码
后端
用户21411832636021 小时前
dify案例分享-零基础上手 Dify TTS 插件!从开发到部署免费文本转语音,测试 + 打包教程全有
后端
架构师沉默1 小时前
Java 开发者别忽略 return!这 11 种写法你写对了吗?
java·后端·架构
EndingCoder1 小时前
React 19 与 Next.js:利用最新 React 功能
前端·javascript·后端·react.js·前端框架·全栈·next.js
RainbowJie11 小时前
Gemini CLI 与 MCP 服务器:释放本地工具的强大潜力
java·服务器·spring boot·后端·python·单元测试·maven
ITMan彪叔1 小时前
Nodejs打包 Webpack 中 __dirname 的正确配置与行为解析
javascript·后端
用户89535603282202 小时前
告别重复,用Go泛型精简Gin代码
后端·gin