从零开始学习 Java:简单易懂的入门指南之Objects、BigInteger、BigDecimal(十四)

简介: 从零开始学习 Java:简单易懂的入门指南之Objects、BigInteger、BigDecimal(十四)

常用API,Objects、BigInteger、BigDecimal

5 Objects类

5.1 概述

5.2 常见方法

6 BigInteger类

6.1 引入

6.2 概述

6.3 常见方法

6.4 底层存储方式:

7 BigDecimal类

7.1 引入

7.2 概述

7.3 常见方法

7.4 底层存储方式:

5 Objects类

5.1 概述

tips:了解内容


查看API文档,我们可以看到API文档中关于Objects类的定义如下:



Objects类所在包是在java.util包下,因此在使用的时候需要进行导包。并且Objects类是被final修饰的,因此该类不能被继承。


Objects类提供了一些对象常见操作的方法。比如判断对象是否相等,判断对象是否为null等等。


接下来我们来查看一下API文档,看一下Objects类中的成员,如下所示:



我们可以发现Objects类中无无参构造方法,因此我们不能使用new关键字去创建Objects的对象。同时我们可以发现Objects类中所提供的方法都是静态的。因此我们可以通过类名直接去调用这些方法。


5.2 常见方法

tips:重点讲解内容


常见方法介绍


我们要重点学习的Objects类中的常见方法如下所示:


public static String toString(Object o)           // 获取对象的字符串表现形式
public static boolean equals(Object a, Object b)      // 比较两个对象是否相等
public static boolean isNull(Object obj)          // 判断对象是否为null
public static boolean nonNull(Object obj)         // 判断对象是否不为null

我们要了解的Objects类中的常见方法如下所示:

public static <T> T requireNonNull(T obj)         // 检查对象是否不为null,如果为null直接抛出异常;如果不是null返回该对象;
public static <T> T requireNonNullElse(T obj, T defaultObj) // 检查对象是否不为null,如果不为null,返回该对象;如果为null返回defaultObj值
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)  // 检查对象是否不为null,如果不为null,返回该对象;如果                              // 为null,返回由Supplier所提供的值

上述方法中的T可以理解为是Object类型。


案例演示


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


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


实现步骤:


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

2.创建一个测试类(ObjectsDemo01), 在该类中编写测试代码

如下所示:


Student类

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

ObjectsDemo01测试类

public class ObjectsDemo01 {
    public static void main(String[] args) {
        // 调用方法
        method_04() ;
    }
    // 测试nonNull方法
    public static void method_04() {
        // 创建一个学生对象
        Student s1 = new Student("it" , "14") ;
        // 调用Objects类中的nonNull方法
        boolean result = Objects.nonNull(s1);
        // 输出结果
        System.out.println(result);
    }
    // 测试isNull方法
    public static void method_03() {
        // 创建一个学生对象
        Student s1 = new Student("it" , "14") ;
        // 调用Objects类中的isNull方法
        boolean result = Objects.isNull(s1);
        // 输出结果
        System.out.println(result);
    }
    // 测试equals方法
    public static void method_02() {
        // 创建两个学生对象
        Student s1 = new Student("it" , "14") ;
        Student s2 = new Student("it" , "14") ;
        // 调用Objects类中的equals方法,比较两个对象是否相等
        boolean result = Objects.equals(s1, s2);     // 如果Student没有重写Object类中的equals方法,此处比较的还是对象的地址值
        // 输出结果
        System.out.println(result);
    }
    // 测试toString方法
    public static void method_01() {
        // 创建一个学生对象
        Student s1 = new Student("it" , "14") ;
        // 调用Objects中的toString方法,获取s1对象的字符串表现形式
        String result = Objects.toString(s1);       // 如果Student没有重写Object类中的toString方法,此处还是返回的对象的地址值
        // 输出结果
        System.out.println(result);
    }
}

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

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

6 BigInteger类

6.1 引入

平时在存储整数的时候,Java中默认是int类型,int类型有取值范围:-2147483648 ~ 2147483647。如果数字过大,我们可以使用long类型,但是如果long类型也表示不下怎么办呢?


就需要用到BigInteger,可以理解为:大的整数。


有多大呢?理论上最大到42亿的21亿次方


基本上在内存撑爆之前,都无法达到这个上限。


6.2 概述

查看API文档,我们可以看到API文档中关于BigInteger类的定义如下:



BigInteger所在包是在java.math包下,因此在使用的时候就需要进行导包。我们可以使用BigInteger类进行大整数的计算

6.3 常见方法

构造方法


public BigInteger(int num, Random rnd)    //获取随机大整数,范围:[0 ~ 2的num次方-1]
public BigInteger(String val)         //获取指定的大整数
public BigInteger(String val, int radix)  //获取指定进制的大整数
下面这个不是构造,而是一个静态方法获取BigInteger对象
public static BigInteger valueOf(long val)  //静态方法获取BigInteger的对象,内部有优化

构造方法小结:


如果BigInteger表示的数字没有超出long的范围,可以用静态方法获取。

如果BigInteger表示的超出long的范围,可以用构造方法获取。

对象一旦创建,BigInteger内部记录的值不能发生改变。

只要进行计算都会产生一个新的BigInteger对象

常见成员方法


BigInteger类中使用最多的还是提供的进行四则运算的方法,如下:

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(BigInteger val)          //转为int类型整数,超出范围数据有误

代码实现:

package com.itheima.a06bigintegerdemo;
import java.math.BigInteger;
public class BigIntegerDemo1 {
    public static void main(String[] args) {
        /*
            public BigInteger(int num, Random rnd) 获取随机大整数,范围:[0~ 2的num次方-11
            public BigInteger(String val) 获取指定的大整数
            public BigInteger(String val, int radix) 获取指定进制的大整数
            public static BigInteger valueOf(long val) 静态方法获取BigInteger的对象,内部有优化
            细节:
            对象一旦创建里面的数据不能发生改变。
        */
        //1.获取一个随机的大整数
        /* Random r=new Random();
            for (int i = e; i < 100; i++) {
            BigInteger bd1 = new BigInteger(4,r);
            System.out.println(bd1);//[@ ~ 15]}
            }
        */
        //2.获取一个指定的大整数,可以超出long的取值范围
        //细节:字符串中必须是整数,否则会报错
        /* BigInteger bd2 = new BigInteger("1.1");
            System.out.println(bd2);
        */
        /*
            BigInteger bd3 = new BigInteger("abc");
            System.out.println(bd3);
         */
        //3.获取指定进制的大整数
        //细节:
        //1.字符串中的数字必须是整数
        //2.字符串中的数字必须要跟进制吻合。
        //比如二进制中,那么只能写日和1,写其他的就报错。
        BigInteger bd4 = new BigInteger("123", 2);
        System.out.println(bd4);
        //4.静态方法获取BigInteger的对象,内部有优化
        //细节:
        //1.能表示范围比较小,只能在long的取值范围之内,如果超出long的范围就不行了。
        //2.在内部对常用的数字: -16 ~ 16 进行了优化。
        //  提前把-16~16 先创建好BigInteger的对象,如果多次获取不会重新创建新的。
        BigInteger bd5 = BigInteger.valueOf(16);
        BigInteger bd6 = BigInteger.valueOf(16);
        System.out.println(bd5 == bd6);//true
        BigInteger bd7 = BigInteger.valueOf(17);
        BigInteger bd8 = BigInteger.valueOf(17);
        System.out.println(bd7 == bd8);//false
        //5.对象一旦创建内部的数据不能发生改变
        BigInteger bd9 =BigInteger.valueOf(1);
        BigInteger bd10 =BigInteger.valueOf(2);
        //此时,不会修改参与计算的BigInteger对象中的借,而是产生了一个新的BigInteger对象记录
        BigInteger result=bd9.add(bd10);
        System.out.println(result);//3
    }
}
package com.itheima.a06bigintegerdemo;
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(BigInteger val) 转为int类型整数,超出范围数据有误
        */
        //1.创建两个BigInteger对象
        BigInteger bd1 = BigInteger.valueOf(10);
        BigInteger bd2 = BigInteger.valueOf(5);
        //2.加法
        BigInteger bd3 = bd1.add(bd2);
        System.out.println(bd3);
        //3.除法,获取商和余数
        BigInteger[] arr = bd1.divideAndRemainder(bd2);
        System.out.println(arr[0]);
        System.out.println(arr[1]);
        //4.比较是否相同
        boolean result = bd1.equals(bd2);
        System.out.println(result);
        //5.次幂
        BigInteger bd4 = bd1.pow(2);
        System.out.println(bd4);
        //6.max
        BigInteger bd5 = bd1.max(bd2);
        //7.转为int类型整数,超出范围数据有误
        /* BigInteger bd6 = BigInteger.valueOf(2147483647L);
         int i = bd6.intValue();
         System.out.println(i);
         */
        BigInteger bd6 = BigInteger.valueOf(200);
        double v = bd6.doubleValue();
        System.out.println(v);//200.0
    }
}

6.4 底层存储方式:

对于计算机而言,其实是没有数据类型的概念的,都是0101010101,数据类型是编程语言自己规定的,所以在实际存储的时候,先把具体的数字变成二进制,每32个bit为一组,存储在数组中。


数组中最多能存储元素个数:21亿多


数组中每一位能表示的数字:42亿多


理论上,BigInteger能表示的最大数字为:42亿的21亿次方。


但是还没到这个数字,电脑的内存就会撑爆,所以一般认为BigInteger是无限的。


存储方式如图所示:



7 BigDecimal类

7.1 引入

首先我们来分析一下如下程序的执行结果:


public class BigDecimalDemo01 {
    public static void main(String[] args) {
        System.out.println(0.09 + 0.01);
    }
}

这段代码比较简单,就是计算0.09和0.01之和,并且将其结果在控制台进行输出。那么按照我们的想法在控制台输出的结果应该为0.1。那么实际的运行结果是什么呢?我们来运行一下程序,控制台的输出

结果如下所示:

0.09999999999999999

这样的结果其实就是一个丢失精度的结果。为什么会产生精度丢失呢?


在使用float或者double类型的数据在进行数学运算的时候,很有可能会产生精度丢失问题。我们都知道计算机底层在进行运算的时候,使用的都是二进制数据; 当我们在程序中写了一个十进制数据 ,在


进行运算的时候,计算机会将这个十进制数据转换成二进制数据,然后再进行运算,计算完毕以后计算机会把运算的结果再转换成十进制数据给我们展示; 如果我们使用的是整数类型的数据进行计算,那


么在把十进制数据转换成二进制数据的时候不会存在精度问题; 如果我们的数据是一个浮点类型的数据,有的时候计算机并不会将这个数据完全转换成一个二进制数据,而是将这个将其转换成一个无限的


趋近于这个十进数的二进制数据; 这样使用一个不太准确的数据进行运算的时候, 最终就会造成精度丢失;为了提高精度,Java就给我们提供了BigDecimal供我们进行数据运算。


7.2 概述

查看API文档,我们可以看到API文档中关于BigDecimal类的定义如下:



BigDecimal所在包是在java.math包下,因此在使用的时候就需要进行导包。我们可以使用BigDecimal类进行更加精准的数据计算。


7.3 常见方法

构造方法


要用BigDecimal类,那么就需要首先学习一下如何去创建BigDecimal的对象。通过查看API文档,我们可以发现Jdk中针对BigDecimal类提供了很多的构造方法,但是最常用的构造方法是:



了解完常见的构造方法以后,我们接下来就重点介绍一下常见的成员方法。

常见成员方法

BigDecimal类中使用最多的还是提供的进行四则运算的方法,如下:


public BigDecimal add(BigDecimal value)       // 加法运算
public BigDecimal subtract(BigDecimal value)    // 减法运算
public BigDecimal multiply(BigDecimal value)    // 乘法运算
public BigDecimal divide(BigDecimal value)      // 触发运算

接下来我们就来通过一些案例演示一下这些成员方法的使用。

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

代码如下所示:

public class BigDecimalDemo01 {
    public static void main(String[] args) {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("0.3") ;
        BigDecimal b2 = new BigDecimal("4") ;
        // 调用方法进行b1和b2的四则运算,并将其运算结果在控制台进行输出
        System.out.println(b1.add(b2));         // 进行加法运算
        System.out.println(b1.subtract(b2));    // 进行减法运算
        System.out.println(b1.multiply(b2));    // 进行乘法运算
        System.out.println(b1.divide(b2));      // 进行除法运算
    }
}

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

4.3
-3.7
1.2
0.075

此时我们可以看到使用BigDecimal类来完成浮点数的计算不会存在损失精度的问题。

案例2:演示除法的特殊情况

如果使用BigDecimal类型的数据进行除法运算的时候,得到的结果是一个无限循环小数,那么就会报错:ArithmeticException。 如下代码所示:

public class BigDecimalDemo02 {
    public static void main(String[] args) {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("1") ;
        BigDecimal b2 = new BigDecimal("3") ;
        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2));
    }
}


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


Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
  at java.base/java.math.BigDecimal.divide(BigDecimal.java:1716)
  at com.itheima.api.bigdecimal.demo02.BigDecimalDemo02.main(BigDecimalDemo02.java:14)

针对这个问题怎么解决,此时我们就需要使用到BigDecimal类中另外一个divide方法,如下所示:

BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

上述divide方法参数说明:

divisor:      除数对应的BigDecimal对象;
scale:        精确的位数;
roundingMode:   取舍模式;
取舍模式被封装到了RoundingMode这个枚举类中(关于枚举我们后期再做重点讲解),在这个枚举类中定义了很多种取舍方式。最常见的取舍方式有如下几个:
UP(直接进1) , FLOOR(直接删除) , HALF_UP(4舍五入),我们可以通过如下格式直接访问这些取舍模式:枚举类名.变量名

接下来我们就来演示一下这些取舍模式,代码如下所示:

public class BigDecimalDemo02 {
    public static void main(String[] args) {
        // 调用方法
        method_03() ;
    }
    // 演示取舍模式HALF_UP
    public static void method_03() {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("0.3") ;
        BigDecimal b2 = new BigDecimal("4") ;
        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2 , 2 , RoundingMode.HALF_UP));
    }
    // 演示取舍模式FLOOR
    public static void method_02() {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("1") ;
        BigDecimal b2 = new BigDecimal("3") ;
        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2 , 2 , RoundingMode.FLOOR));
    }
    // 演示取舍模式UP
    public static void method_01() {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("1") ;
        BigDecimal b2 = new BigDecimal("3") ;
        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2 , 2 , RoundingMode.UP));
    }
}

小结:后期在进行两个数的除法运算的时候,我们常常使用的是可以设置取舍模式的divide方法。

7.4 底层存储方式:

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



后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹

相关文章
|
15天前
|
安全 Java 数据库连接
2025 年最新 Java 学习路线图含实操指南助你高效入门 Java 编程掌握核心技能
2025年最新Java学习路线图,涵盖基础环境搭建、核心特性(如密封类、虚拟线程)、模块化开发、响应式编程、主流框架(Spring Boot 3、Spring Security 6)、数据库操作(JPA + Hibernate 6)及微服务实战,助你掌握企业级开发技能。
143 3
|
3月前
|
IDE Java 数据挖掘
Java 基础类从入门到精通实操指南
这份指南专注于**Java 17+**的新特性和基础类库的现代化用法,涵盖开发环境配置、数据类型增强(如文本块)、字符串与集合处理进阶、异常改进(如密封类)、IO操作及实战案例。通过具体代码示例,如CSV数据分析工具,帮助开发者掌握高效编程技巧。同时提供性能优化建议和常用第三方库推荐,适合从入门到精通的Java学习者。资源链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
171 35
|
3月前
|
Java API 微服务
2025 年 Java 从入门到精通学习笔记全新版
《Java学习笔记:从入门到精通(2025更新版)》是一本全面覆盖Java开发核心技能的指南,适合零基础到高级开发者。内容包括Java基础(如开发环境配置、核心语法增强)、面向对象编程(密封类、接口增强)、进阶技术(虚拟线程、结构化并发、向量API)、实用类库与框架(HTTP客户端、Spring Boot)、微服务与云原生(容器化、Kubernetes)、响应式编程(Reactor、WebFlux)、函数式编程(Stream API)、测试技术(JUnit 5、Mockito)、数据持久化(JPA、R2DBC)以及实战项目(Todo应用)。
196 5
|
3月前
|
监控 Java 测试技术
2025 年 Java 核心技术从入门到精通实战指南
《2025年Java核心技术实战指南》全面覆盖Java开发的最新趋势与最佳实践。内容包括Java新特性(如模式匹配、文本块、记录类)、微服务架构(Spring Boot 3.0+、Spring Cloud)、响应式编程(Reactor、WebFlux)、容器化与云原生(Docker、Kubernetes)、数据访问技术(JPA、R2DBC)、函数式编程、单元测试与集成测试(JUnit 5、Mockito)、性能优化与监控等。通过实战案例,帮助开发者掌握构建高性能、高可用系统的技能。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
194 7
|
3月前
|
消息中间件 Java 微服务
2025 版 Java 学习路线实战指南从入门到精通
《Java学习路线实战指南(2025版)》是一份全面的Java开发学习手册,涵盖基础环境搭建、核心语法与新特性、数据结构与算法、微服务架构、云原生技术栈、AI融合及项目实战。内容包括JDK安装配置、IntelliJ IDEA设置、Records类与模式匹配增强、LeetCode题解、Spring Cloud微服务开发、Kubernetes部署、OpenAI API调用等。结合在线商城系统案例,采用Vue 3、Spring Boot 3.5、MySQL、Elasticsearch等技术,提供从理论到实践的完整路径,助力开发者掌握2025年最新趋势与最佳实践。
304 4
|
24天前
|
前端开发 Java 数据库
Java 项目实战从入门到精通 :Java Web 在线商城项目开发指南
本文介绍了一个基于Java Web的在线商城项目,涵盖技术方案与应用实例。项目采用Spring、Spring MVC和MyBatis框架,结合MySQL数据库,实现商品展示、购物车、用户注册登录等核心功能。通过Spring Boot快速搭建项目结构,使用JPA进行数据持久化,并通过Thymeleaf模板展示页面。项目结构清晰,适合Java Web初学者学习与拓展。
139 1
|
18天前
|
算法 Java 测试技术
零基础学 Java: 从语法入门到企业级项目实战的详细学习路线解析
本文为零基础学习者提供完整的Java学习路线,涵盖语法基础、面向对象编程、数据结构与算法、多线程、JVM原理、Spring框架、Spring Boot及项目实战,助你从入门到进阶,系统掌握Java编程技能,提升实战开发能力。
61 0
|
2月前
|
存储 缓存 NoSQL
java 集合入门基础理论的核心概念与实用长尾知识
本文介绍了Java集合框架的基础理论知识,包括单列集合(List、Set、Queue)和双列集合(Map)的特点及常用实现类(如ArrayList、HashSet、HashMap等)。详细讲解了集合的遍历方式(迭代器、增强for循环、Lambda表达式)和典型应用场景(如数据去重、键值存储等)。通过具体代码示例,帮助初学者理解集合框架的核心概念和实际应用,为Java编程中的数据存储与管理提供基础指导。
70 0
|
2月前
|
缓存 NoSQL Java
Java Web 从入门到精通之苍穹外卖项目实战技巧
本项目为JavaWeb综合实战案例——苍穹外卖系统,涵盖Spring Boot 3、Spring Cloud Alibaba、Vue 3等主流技术栈,涉及用户认证、订单处理、Redis缓存、分布式事务、系统监控及Docker部署等核心功能,助你掌握企业级项目开发全流程。
240 0
|
2月前
|
存储 安全 Java
Java 学习路线 35 掌握 List 集合从入门到精通的 List 集合核心知识
本文详细解析Java中List集合的原理、常用实现类(如ArrayList、LinkedList)、核心方法及遍历方式,并结合数据去重、排序等实际应用场景,帮助开发者掌握List在不同业务场景下的高效使用,提升Java编程能力。
273 0