关于后端:Java-的常见-API-与对象克隆

45次阅读

共计 29343 个字符,预计需要花费 74 分钟才能阅读完成。

1 Math 类

1.1 概述

tips:理解内容

查看 API 文档,咱们能够看到 API 文档中对于 Math 类的定义如下:

Math 类所在包为 java.lang 包,因而在应用的时候不须要进行导包。并且 Math 类被 final 润饰了,因而该类是不能被继承的。

Math 类蕴含执行根本数字运算的办法,咱们能够应用 Math 类实现根本的数学运算。

要想应用 Math 类咱们就须要先创立该类的对象,那么创建对象就须要借助于构造方法。因而咱们就须要首先查看一下 API 文档,看看 API 文档中针对 Math 类有没有提供对应的构造方法。通过 API 文档来查看

一下 Math 类的成员,如下所示:

在 API 文档中没有体现可用的构造方法,因而咱们就不能间接通过 new 关键字去创立 Math 类的对象。同时咱们发现 Math 类中的办法都是动态的,因而在应用的时候咱们能够间接通过类名去调用。在 Math 类中

定义了很多数学运算的办法,然而咱们并不可能将所有的办法学习一遍,咱们次要学习的就是一些常见的办法。

1.2 常见办法

tips:重点解说内容

<font color=”red” size=”3″>常见办法介绍</font>

咱们要学习的 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)                // 依照四舍五入返回最靠近参数的 int 类型的值
public static int max(int a,int b)                // 获取两个 int 值中的较大值
public static int min(int a,int b)                // 获取两个 int 值中的较小值
public static double pow (double a,double b)    // 计算 a 的 b 次幂的值
public static double random()                    // 返回一个 [0.0,1.0) 的随机值

<font color=”red” size=”3″>案例演示</font>

接下来咱们就来演示一些这些办法的执行成果,如下所示:

public class MathDemo01 {public static void main(String[] args) {// public static int abs(int a)         返回参数的绝对值
        System.out.println("- 2 的绝对值为:" + Math.abs(-2));
        System.out.println("2 的绝对值为:" + Math.abs(2));

        // public static double ceil(double a)  返回大于或等于参数的最小整数
        System.out.println("大于或等于 23.45 的最小整数位:" + Math.ceil(23.45));
        System.out.println("大于或等于 -23.45 的最小整数位:" + Math.ceil(-23.45));

        // public static double floor(double a) 返回小于或等于参数的最大整数
        System.out.println("小于或等于 23.45 的最大整数位:" + Math.floor(23.45));
        System.out.println("小于或等于 -23.45 的最大整数位:" + Math.floor(-23.45));

        // public static int round(float a)     依照四舍五入返回最靠近参数的 int
        System.out.println("23.45 四舍五入的后果为:" + Math.round(23.45));
        System.out.println("23.55 四舍五入的后果为:" + Math.round(23.55));

        // public static int max(int a,int b)   返回两个 int 值中的较大值
        System.out.println("23 和 45 的最大值为:" + Math.max(23, 45));

        // public static int min(int a,int b)   返回两个 int 值中的较小值
        System.out.println("12 和 34 的最小值为:" + Math.min(12 , 34));

        // public static double pow (double a,double b)返回 a 的 b 次幂的值
        System.out.println("2 的 3 次幂计算结果为:" + Math.pow(2,3));

        // public static double random()返回值为 double 的正值,[0.0,1.0)
        System.out.println("获取到的 0 - 1 之间的随机数为:" + Math.random());
    }

}

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

- 2 的绝对值为:2
2 的绝对值为:2
大于或等于 23.45 的最小整数位:24.0
大于或等于 -23.45 的最小整数位:-23.0
小于或等于 23.45 的最大整数位:23.0
小于或等于 -23.45 的最大整数位:-24.0
23.45 四舍五入的后果为:23
23.55 四舍五入的后果为:24
23 和 45 的最大值为: 45
12 和 34 的最小值为: 12
2 的 3 次幂计算结果为: 8.0
获取到的 0 - 1 之间的随机数为: 0.7322484131745958

1.3 算法小题(质数)

需要:

​ 判断一个数是否为一个质数

代码实现:

public class MathDemo2 {public static void main(String[] args) {
        // 判断一个数是否为一个质数
        System.out.println(isPrime(997));
        //997 2~996 995 次
    }

    public static boolean isPrime(int number) {
        int count = 0;
        for (int i = 2; i <= Math.sqrt(number); i++) {
            count++;
            if (number % i == 0) {return false;}
        }
        System.out.println(count);
        return true;
    }
}

1.4 算法小题(自幂数)

自幂数,一个 n 位自然数等于本身各个数位上数字的 n 次幂之和

​ 举例 1:三位数 1^3 + 5^3 + 3^3 = 153

​ 举例 2:四位数 1^4 + 6^4 + 3^4 + 4^3 = 1634

如果自幂数是:

  • 一位自幂数,也叫做:单身数
  • 三位自幂数:水仙花数 四位自幂数:四叶玫瑰数
  • 五位自幂数:五角星数 六位自幂数:六合数
  • 七位自幂数:北斗七星数 八位自幂数:八仙数
  • 九位自幂数:九九重阳数 十位自幂数:美中不足数

要求 1:统计一共有多少个水仙花数。

要求 2:(课后作业)证实没有两位的自幂数。

要求 3:(课后作业)别离统计有多少个四叶玫瑰数和五角星数。(答案:都是 3 个)

// 水仙花数:100 ~ 999
int count = 0;
// 失去每一个三位数
for (int i = 100; i <= 999; i++) {
    // 个位 十位 百位
    int ge = i % 10;
    int shi = i / 10 % 10;
    int bai = i / 100 % 10;
    // 判断:
    // 每一位的三次方之和 跟自身 进行比拟。double sum = Math.pow(ge, 3) + Math.pow(shi, 3) + Math.pow(bai, 3);
    if (sum == i) {
        count++;
        //System.out.println(i);

        System.out.println(count);
    }
}

2 System 类

2.1 概述

tips:理解内容

查看 API 文档,咱们能够看到 API 文档中对于 System 类的定义如下:

System 类所在包为 java.lang 包,因而在应用的时候不须要进行导包。并且 System 类被 final 润饰了,因而该类是不能被继承的。

System 蕴含了零碎操作的一些罕用的办法。比方获取以后工夫所对应的毫秒值,再比方终止以后 JVM 等等。

要想应用 System 类咱们就须要先创立该类的对象,那么创建对象就须要借助于构造方法。因而咱们就须要首先查看一下 API 文档,看看 API 文档中针对 System 类有没有提供对应的构造方法。通过 API 文档来

查看一下 System 类的成员,如下所示:

在 API 文档中没有体现可用的构造方法,因而咱们就不能间接通过 new 关键字去创立 System 类的对象。同时咱们发现 System 类中的办法都是动态的,因而在应用的时候咱们能够间接通过类名去调用(Nested

Class Summary 外部类或者外部接口的形容)。

2.2 常见办法

tips:重点解说内容

<font color=”red” size=”3″>常见办法介绍</font>

咱们要学习的 System 类中的常见办法如下所示:

public static long currentTimeMillis()            // 获取以后工夫所对应的毫秒值(以后工夫为 0 时区所对应的工夫即就是英国格林尼治天文台原址所在位置)public static void exit(int status)                // 终止以后正在运行的 Java 虚拟机,0 示意失常退出,非零示意异样退出
public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos, int length); // 进行数值元素 copy

<font color=”red” size=”3″>案例演示</font>

接下来咱们就来通过一些案例演示一下这些办法的特点。

<font color=”blue” size=”2″>案例 1 </font>:演示 currentTimeMillis 办法

public class SystemDemo01 {public static void main(String[] args) {

        // 获取以后工夫所对应的毫秒值
        long millis = System.currentTimeMillis();

        // 输入后果
        System.out.println("以后工夫所对应的毫秒值为:" + millis);

    }

}

运行程序进行测试,控制台的输入后果如下:

以后工夫所对应的毫秒值为:1576050298343

获取到以后工夫的毫秒值的意义:咱们经常来须要统计某一段代码的执行工夫。此时咱们就能够在执行这段代码之前获取一次工夫,在执行结束当前再次获取一次零碎工夫,而后计算两个工夫的差值,

这个差值就是这段代码执行结束当前所须要的工夫。如下代码所示:

public class SystemDemo2 {public static void main(String[] args) {
        // 判断 1~100000 之间有多少个质数

        long start = System.currentTimeMillis();

        for (int i = 1; i <= 100000; i++) {boolean flag = isPrime2(i);
            if (flag) {System.out.println(i);
            }
        }
        long end = System.currentTimeMillis();
        // 获取程序运行的总工夫
        System.out.println(end - start); // 形式一:1514 毫秒  形式二:71 毫秒
    }

    // 以前判断是否为质数的形式
    public static boolean isPrime1(int number) {for (int i = 2; i < number; i++) {if (number % i == 0) {return false;}
        }
        return true;
    }

    // 改良之后判断是否为质数的形式(效率高)public static boolean isPrime2(int number) {for (int i = 2; i <= Math.sqrt(number); i++) {if (number % i == 0) {return false;}
        }
        return true;
    }
}

<font color=”blue” size=”2″>案例 2 </font>:演示 exit 办法

public class SystemDemo01 {public static void main(String[] args) {
        
        // 输入
        System.out.println("程序开始执行了.....");
        
        // 终止 JVM
        System.exit(0);
        
        // 输入
        System.out.println("程序终止了..........");
        
    }
    
}

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

程序开始执行了.....

此时能够看到在控制台只输入了 ” 程序开始了 …”,因为 JVM 终止了,因而输入 ” 程序终止了 …” 这段代码没有被执行。

<font color=”blue” size=”2″>案例 3 </font>:演示 arraycopy 办法

办法参数阐明:

// src:      源数组
// srcPos:源数值的开始地位
// dest:指标数组
// destPos:指标数组开始地位
// length:   要复制的元素个数
public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos, int length); 

代码如下所示:

public class SystemDemo01 {public static void main(String[] args) {

        // 定义源数组
        int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56} ;

        // 定义指标数组
        int[] desArray = new int[10] ;

        // 进行数组元素的 copy: 把 srcArray 数组中从 0 索引开始的 3 个元素,从 desArray 数组中的 1 索引开始复制过来
        System.arraycopy(srcArray , 0 , desArray , 1 , 3);

        // 遍历指标数组
        for(int x = 0 ; x < desArray.length ; x++) {if(x != desArray.length - 1) {System.out.print(desArray[x] + ",");
            }else {System.out.println(desArray[x]);
            }

        }

    }

}

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

0, 23, 45, 67, 0, 0, 0, 0, 0, 0

通过控制台输入后果咱们能够看到,数组元素确实进行复制了。

应用这个办法咱们也能够实现数组元素的删除操作,如下所示:

public class SystemDemo02 {public static void main(String[] args) {
        // 定义一个数组
        int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56} ;
        // 删除数组中第 3 个元素(67):要删除 67 这个元素,咱们只须要将 67 前面的其余元素顺次向前进行挪动即可
        System.arraycopy(srcArray , 3 , srcArray , 2 , 3);
        // 遍历 srcArray 数组
        for(int x = 0 ; x < srcArray.length ; x++) {if(x != desArray.length - 1) {System.out.print(srcArray[x] + ",");
            }else {System.out.println(srcArray[x]);
            }
        }
    }
}

运行程序进行测试,控制台的输入后果如下所示:

23, 45, 89, 14, 56, 56 

通过控制台输入后果咱们能够看到此时多出了一个 56 元素,此时咱们只须要将最初一个地位设置为 0 即可。如下所示:

public class SystemDemo02 {public static void main(String[] args) {
        // 定义一个数组
        int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56} ;
        // 删除数组中第 3 个元素(67):要删除 67 这个元素,咱们只须要将 67 前面的其余元素顺次向前进行挪动即可
        System.arraycopy(srcArray , 3 , srcArray , 2 , 3);
        // 将最初一个地位的元素设置为 0
        srcArray[srcArray.length - 1] = 0 ;
        // 遍历 srcArray 数组
        for(int x = 0 ; x < srcArray.length ; x++) {if(x != srcArray.length - 1) {System.out.print(srcArray[x] + ",");
            }else {System.out.println(srcArray[x]);
            }
        }
    }
}

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

23, 45, 89, 14, 56, 0

此时咱们能够看到元素 ”67″ 曾经被删除掉了。67 前面的其余元素顺次向前进行挪动了一位。

arraycopy 办法底层细节:

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

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

3. 如果数据源数组和目的地数组都是援用数据类型,那么子类类型能够赋值给父类类型

代码示例:

public class SystemDemo3 {public static void main(String[] args) {//public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数) 数组拷贝
        // 细节:
        //1. 如果数据源数组和目的地数组都是根本数据类型,那么两者的类型必须保持一致,否则会报错
        //2. 在拷贝的时候须要思考数组的长度,如果超出范围也会报错
        //3. 如果数据源数组和目的地数组都是援用数据类型,那么子类类型能够赋值给父类类型

        Student s1 = new Student("zhangsan", 23);
        Student s2 = new Student("lisi", 24);
        Student s3 = new Student("wangwu", 25);

        Student[] arr1 = {s1, s2, s3};
        Person[] arr2 = new Person[3];
        // 把 arr1 中对象的地址值赋值给 arr2 中
        System.arraycopy(arr1, 0, arr2, 0, 3);

        // 遍历数组 arr2
        for (int i = 0; i < arr2.length; i++) {Student stu = (Student) arr2[i];
            System.out.println(stu.getName() + "," + stu.getAge());
        }
    }
}

class Person {
    private String name;
    private int age;

    public Person() {}

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

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {return name;}

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {this.name = name;}

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {return age;}

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {this.age = age;}

    public String toString() {return "Person{name =" + name + ", age =" + age + "}";
    }
}


class Student extends Person {public Student() { }

    public Student(String name, int age) {super(name, age);
    }
}

3 Runtime

3.1 概述

​ Runtime 示意 Java 中运行时对象,能够获取到程序运行时设计到的一些信息

3.2 常见办法

<font color=”red” size=”3″>常见办法介绍</font>

咱们要学习的 Object 类中的常见办法如下所示:

public static Runtime getRuntime()        // 以后零碎的运行环境对象
public void exit(int status)            // 进行虚拟机
public int availableProcessors()        // 取得 CPU 的线程数
public long maxMemory()                    //JVM 能从零碎中获取总内存大小(单位 byte)public long totalMemory()                //JVM 曾经从零碎中获取总内存大小(单位 byte)public long freeMemory()                //JVM 残余内存大小(单位 byte)public Process exec(String command)     // 运行 cmd 命令

代码示例:

public class RunTimeDemo1 {public static void main(String[] args) throws IOException {
        /*
            public static Runtime getRuntime() 以后零碎的运行环境对象
            public void exit(int status) 进行虚拟机
            public int availableProcessors() 取得 CPU 的线程数
            public long maxMemory() JVM 能从零碎中获取总内存大小(单位 byte)
            public long totalMemory() JVM 曾经从零碎中获取总内存大小(单位 byte)
            public long freeMemory() JVM 残余内存大小(单位 byte)
            public Process exec(string command) 运行 cmd 命令
        */

        //1. 获取 Runtime 的对象
        //Runtime r1 =Runtime.getRuntime();

        //2.exit 进行虚拟机
        //Runtime.getRuntime().exit(0);
        //System.out.println("看看我执行了吗?");


        //3. 取得 CPU 的线程数
        System.out.println(Runtime.getRuntime().availableProcessors());//8
        //4. 总内存大小, 单位 byte 字节
        System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);//4064
        //5. 曾经获取的总内存大小, 单位 byte 字节
        System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);//254
        //6. 残余内存大小
        System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);//251

        //7. 运行 cmd 命令
        //shutdown : 关机
        // 加上参数能力执行
        //-s : 默认在 1 分钟之后关机
        //-s -t 指定工夫 : 指定关机工夫
        //-a : 勾销关机操作
        //-r: 关机并重启
        Runtime.getRuntime().exec("shutdown -s -t 3600");


    }
}

3.3 恶搞好基友

需要:

​ 界面上方按钮默认暗藏

​ 界面两头有一个提醒文本和三个按钮

​ 当你的好基友点击两头三个按钮的时候就在 N 秒之后关机,不同的按钮 N 的值不一样

​ 任意一个按钮被点击之后,上方了按钮呈现。当点击上方按钮之后勾销关机工作

public class Test {public static void main(String[] args) {new MyJframe();
    }
}
public class MyJframe extends JFrame implements ActionListener {JButton yesBut = new JButton("帅爆了");
    JButton midBut = new JButton("一般般吧");
    JButton noBut = new JButton("不帅,有点磕碜");
    JButton dadBut = new JButton("饶了我吧!");


    // 决定了上方的按钮是否展现
    boolean flag = false;


    public MyJframe() {initJFrame();


        initView();


        // 显示
        this.setVisible(true);
    }

    private void initView() {this.getContentPane().removeAll();

        if (flag) {
            // 展现按钮
            dadBut.setBounds(50, 20, 100, 30);
            dadBut.addActionListener(this);
            this.getContentPane().add(dadBut);
        }


        JLabel text = new JLabel("你感觉本人帅吗?");
        text.setFont(new Font("微软雅黑", 0, 30));
        text.setBounds(120, 150, 300, 50);


        yesBut.setBounds(200, 250, 100, 30);
        midBut.setBounds(200, 325, 100, 30);
        noBut.setBounds(160, 400, 180, 30);

        yesBut.addActionListener(this);
        midBut.addActionListener(this);
        noBut.addActionListener(this);

        this.getContentPane().add(text);
        this.getContentPane().add(yesBut);
        this.getContentPane().add(midBut);
        this.getContentPane().add(noBut);

        this.getContentPane().repaint();
    }

    private void initJFrame() {
        // 设置宽高
        this.setSize(500, 600);
        // 设置题目
        this.setTitle("恶搞好基友");
        // 设置敞开模式
        this.setDefaultCloseOperation(3);
        // 置顶
        this.setAlwaysOnTop(true);
        // 居中
        this.setLocationRelativeTo(null);
        // 勾销外部默认布局
        this.setLayout(null);
    }

    @Override
    public void actionPerformed(ActionEvent e) {Object obj = e.getSource();
        if (obj == yesBut) {
            // 给好基友一个弹框
            showJDialog("xxx,你太自信了,给你一点小惩办");
            try {Runtime.getRuntime().exec("shutdown -s -t 3600");
            } catch (IOException ioException) {ioException.printStackTrace();
            }
            flag = true;
            initView();} else if (obj == midBut) {System.out.println("你的好基友点击了一般般吧");

            // 给好基友一个弹框
            showJDialog("xxx,你还是太自信了,也要给你一点小惩办");

            try {Runtime.getRuntime().exec("shutdown -s -t 7200");
            } catch (IOException ioException) {ioException.printStackTrace();
            }

            flag = true;
            initView();} else if (obj == noBut) {System.out.println("你的好基友点击了不帅");

            // 给好基友一个弹框
            showJDialog("xxx,你还是有一点自知之明的,也要给你一点小惩办");

            try {Runtime.getRuntime().exec("shutdown -s -t 1800");
            } catch (IOException ioException) {ioException.printStackTrace();
            }

            flag = true;
            initView();} else if (obj == dadBut) {
            // 给好基友一个弹框
            showJDialog("xxx,这次就饶了你~");

            try {Runtime.getRuntime().exec("shutdown -a");
            } catch (IOException ioException) {ioException.printStackTrace();
            }

        }
    }

    public void showJDialog(String content) {
        // 创立一个弹框对象
        JDialog jDialog = new JDialog();
        // 给弹框设置大小
        jDialog.setSize(200, 150);
        // 让弹框置顶
        jDialog.setAlwaysOnTop(true);
        // 让弹框居中
        jDialog.setLocationRelativeTo(null);
        // 弹框不敞开永远无奈操作上面的界面
        jDialog.setModal(true);

        // 创立 Jlabel 对象治理文字并增加到弹框当中
        JLabel warning = new JLabel(content);
        warning.setBounds(0, 0, 200, 150);
        jDialog.getContentPane().add(warning);

        // 让弹框展现进去
        jDialog.setVisible(true);
    }
}

4 Object 类

4.1 概述

tips:重点解说内容

查看 API 文档,咱们能够看到 API 文档中对于 Object 类的定义如下:

Object 类所在包是 java.lang 包。Object 是类层次结构的根,每个类都能够将 Object 作为超类。所有类都间接或者间接的继承自该类;换句话说,该类所具备的办法,其余所有类都继承了。

查看 API 文档咱们能够看到,在 Object 类中提供了一个无参构造方法,如下所示:

然而个别状况下咱们很少去被动的创立 Object 类的对象,调用其对应的办法。更多的是创立 Object 类的某个子类对象,而后通过子类对象调用 Object 类中的办法。

4.2 常见办法

tips:重点解说内容

<font color=”red” size=”3″>常见办法介绍</font>

咱们要学习的 Object 类中的常见办法如下所示:

public String toString()                // 返回该对象的字符串示意模式(能够看做是对象的内存地址值)
public boolean equals(Object obj)        // 比拟两个对象地址值是否相等;true 示意雷同,false 示意不雷同
protected Object clone()                // 对象克隆

<font color=”red” size=”3″>案例演示</font>

接下来咱们就来通过一些案例演示一下这些办法的特点。

<font color=”blue” size=”2″>案例 1 </font>:演示 toString 办法

实现步骤:

  1. 创立一个学生类,提供两个成员变量(name,age);并且提供对应的无参构造方法和有参构造方法以及 get/set 办法
  2. 创立一个测试类(ObjectDemo01),在测试类的 main 办法中去创立学生对象,而后调用该对象的 toString 办法获取该对象的字符串表现形式,并将后果进行输入

如下所示:

Student 类

public class Student {

    private String name ;       // 姓名
    private String age ;        // 年龄

    // 无参构造方法和有参构造方法以及 get 和 set 办法略
    ...
        
}

ObjectDemo01 测试类

public class ObjectDemo01 {public static void main(String[] args) {

        // 创立学生对象
        Student s1 = new Student("itheima" , "14") ;

        // 调用 toString 办法获取 s1 对象的字符串表现形式
        String result1 = s1.toString();

        // 输入后果
        System.out.println("s1 对象的字符串表现形式为:" + result1);

    }

}

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

s1 对象的字符串表现形式为:com.itheima.api.system.demo04.Student@3f3afe78

为什么控制台输入的后果为:com.itheima.api.system.demo04.Student@3f3afe78;此时咱们能够查看一下 Object 类中 toString 办法的源码,如下所示:

public String toString() {        // Object 类中 toString 办法的源码定义
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

其中 getClass().getName()对应的后果就是:com.itheima.api.system.demo04.Student;Integer.toHexString(hashCode())对应的后果就是 3f3afe78。

咱们经常将 ”com.itheima.api.system.demo04.Student@3f3afe78″ 这一部分称之为对象的内存地址值。然而个别状况下获取对象的内存地址值没有太大的意义。获取对象的成员变量的字符串拼接模式才

算有意义,怎么实现呢?此时咱们就须要在 Student 类中重写 Object 的 toString 办法。咱们能够通过 idea 开发工具进行实现,具体步骤如下所示:

  1. 在空白处应用快捷键:alt + insert。此时会弹出如下的对话框
  1. 抉择 toString,此时会弹出如下的对话框

同时抉择 name 和 age 属性,点击 OK。此时就会实现 toString 办法的重写,代码如下所示:

@Override
public String toString() {
    return "Student{" +
        "name='" + name + '\'' +
        ", age='" + age + '\'' +
        '}';
}

这段代码就是把 Student 类中的成员变量进行了字符串的拼接。重写结束当前,再次运行程序,控制台输入后果如下所示:

s1 对象的字符串表现形式为:Student{name='itheima', age='14'}

此时咱们就能够分明的查看 Student 的成员变量值,因而重写 toString 办法的意义就是以良好的格局,更不便的展现对象中的属性值

咱们再来查看一下如下代码的输入:

// 创立学生对象
Student s1 = new Student("itheima" , "14") ;

// 间接输入对象 s1
System.out.println(s1);

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

Student{name='itheima', age='14'}

咱们能够看到和方才的输入后果是统一的。那么此时也就证实间接输入一个对象,那么会默认调用对象的 toString 办法,因而如上代码的等同于如下代码:

// 创立学生对象
Student s1 = new Student("itheima" , "14") ;

// 调用 s1 的 toString 办法,把后果进行输入
System.out.println(s1.toString());

因而前期为了不便进行测试,咱们经常是通过输入语句间接输入一个对象的名称。

小结:

  1. 在通过输入语句输入一个对象时,默认调用的就是 toString()办法
  2. 输入地址值个别没有意义,咱们能够通过重写 toString 办法去输入对应的成员变量信息(快捷键:atl + insert,空白处 右键 -> Generate -> 抉择 toString)
  3. toString 办法的作用:以良好的格局,更不便的展现对象中的属性值
  4. 个别状况下 Jdk 所提供的类都会重写 Object 类中的 toString 办法

<font color=”blue” size=”2″>案例 2 </font>:演示 equals 办法

实现步骤:

  1. 在测试类(ObjectDemo02)的 main 办法中,创立两个学生对象,而后比拟两个对象是否雷同

代码如下所示:

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 == s2);

    }

}

运行程序进行测试,控制台的输入后果如下所示:

false

因为 ”==” 号比拟的是对象的地址值,而咱们通过 new 关键字创立了两个对象,它们的地址值是不雷同的。因而比拟后果就是 false。

咱们尝试调用 Object 类中的 equals 办法进行比拟,代码如下所示:

// 调用 equals 办法比拟两个对象是否相等
boolean result = s1.equals(s2);

// 输入后果
System.out.println(result);

运行程序进行测试,控制台的输入后果为:

false

为什么后果还是 false 呢?咱们能够查看一下 Object 类中 equals 办法的源码,如下所示:

public boolean equals(Object obj) {        // Object 类中的 equals 办法的源码
    return (this == obj);
}

通过源码咱们能够发现默认状况下 equals 办法比拟的也是对象的地址值。比拟内存地址值个别状况下是没有意义的,咱们心愿比拟的是对象的属性,如果两个对象的属性雷同,咱们认为就是同一个对象;

那么要比拟对象的属性,咱们就须要在 Student 类中重写 Object 类中的 equals 办法。equals 办法的重写,咱们也能够应用 idea 开发工具实现,具体的操作如下所示:

  1. 在空白处应用快捷键:alt + insert。此时会弹出如下的对话框
  1. 抉择 equals() and hashCode()办法,此时会弹出如下的对话框

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

抉择 neme 和 age 属性点击 next,此时就会弹出如下对话框:

勾销 name 和 age 属性(因为此时抉择的是在生成 hashCode 办法时所波及到的属性,对于 hashCode 办法前期再做重点介绍),点击 Finish 实现生成操作。生成的 equals 办法和 hashCode 办法如下:

@Override
public boolean equals(Object o) {if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return Objects.equals(name, student.name) && Objects.equals(age, student.age);    // 比拟的是对象的 name 属性值和 age 属性值
}

@Override
public int hashCode() {return 0;}

hashCode 办法咱们临时应用不到,能够将 hashCode 办法删除。重写结束当前运行程序进行测试,控制台输入后果如下所示:

true

此时 equals 办法比拟的是对象的成员变量值,而 s1 和 s2 两个对象的成员变量值都是雷同的。因而比拟结束当前的后果就是 true。

小结:

  1. 默认状况下 equals 办法比拟的是对象的地址值
  2. 比拟对象的地址值是没有意义的,因而个别状况下咱们都会重写 Object 类中的 equals 办法

<font color=”blue” size=”2″>案例 2 </font>:对象克隆

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

对象克隆的分类:

深克隆和浅克隆

浅克隆:

​ 不论对象外部的属性是根本数据类型还是援用数据类型,都齐全拷贝过去

​ 根本数据类型拷贝过去的是具体的数据,援用数据类型拷贝过去的是地址值。

​ Object 类默认的是浅克隆

深克隆:

​ 根本数据类型拷贝过去,字符串复用,援用数据类型会从新创立新的

代码实现:

package com.itheima.a04objectdemo;

public class ObjectDemo4 {public static void main(String[] args) throws CloneNotSupportedException {// protected object clone(int a) 对象克隆 

        //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. 克隆对象
        // 细节:
        // 办法在底层会帮咱们创立一个对象, 并把原对象中的数据拷贝过来。// 书写细节:
        //1. 重写 Object 中的 clone 办法
        //2. 让 javabean 类实现 Cloneable 接口
        //3. 创立原对象并调用 clone 就能够了
        //User u2 =(User)u1.clone();

        // 验证一件事件:Object 中的克隆是浅克隆
        // 想要进行深克隆,就须要重写 clone 办法并批改外面的办法体
        //int[] arr = u1.getData();
        //arr[0] = 100;

        //System.out.println(u1);
        //System.out.println(u2);


        // 当前个别会用第三方工具进行克隆
        //1. 第三方写的代码导入到我的项目中
        //2. 编写代码
        //Gson gson =new Gson();
        // 把对象变成一个字符串
        //String s=gson.toJson(u1);
        // 再把字符串变回对象就能够了
        //User user =gson.fromJson(s, User.class);

        //int[] arr=u1.getData();
        //arr[0] = 100;

        // 打印对象
        //System.out.println(user);

    }
}

package com.itheima.a04objectdemo;

import java.util.StringJoiner;



//Cloneable
// 如果一个接口外面没有形象办法
// 示意以后的接口是一个标记性接口
// 当初 Cloneable 示意一旦实现了,那么以后类的对象就能够被克降
// 如果没有实现,以后类的对象就不能克隆
public class User implements Cloneable {
    private int id;
    private String username;
    private String password;
    private String path;
    private int[] data;




    public User() {}

    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;
    }

    /**
     * 获取
     *
     * @return id
     */
    public int getId() {return id;}

    /**
     * 设置
     *
     * @param id
     */
    public void setId(int id) {this.id = id;}

    /**
     * 获取
     *
     * @return username
     */
    public String getUsername() {return username;}

    /**
     * 设置
     *
     * @param username
     */
    public void setUsername(String username) {this.username = username;}

    /**
     * 获取
     *
     * @return password
     */
    public String getPassword() {return password;}

    /**
     * 设置
     *
     * @param password
     */
    public void setPassword(String password) {this.password = password;}

    /**
     * 获取
     *
     * @return path
     */
    public String getPath() {return path;}

    /**
     * 设置
     *
     * @param path
     */
    public void setPath(String path) {this.path = path;}

    /**
     * 获取
     *
     * @return data
     */
    public int[] getData() {return data;}

    /**
     * 设置
     *
     * @param data
     */
    public void setData(int[] data) {this.data = data;}

    public String toString() {return "角色编号为:" + id + ",用户名为:" + username + "明码为:" + password + ", 游戏图片为:" + path + ", 进度:" + arrToString();
    }


    public String arrToString() {StringJoiner sj = new StringJoiner(",", "[", "]");

        for (int i = 0; i < data.length; i++) {sj.add(data[i] + "");
        }
        return sj.toString();}

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 调用父类中的 clone 办法
        // 相当于让 Java 帮咱们克隆一个对象,并把克隆之后的对象返回进来。// 先把被克隆对象中的数组获取进去
        int[] data = this.data;
        // 创立新的数组
        int[] newData =new int[data.length];
        // 拷贝数组中的数据
        for (int i = 0; i < data.length; i++) {newData[i] = data[i];
        }
        // 调用父类中的办法克隆对象
            User u=(User)super.clone();
        // 因为父类中的克隆办法是浅克隆,替换克隆进去对象中的数组地址值
        u.data =newData;
        return u;
    }
}

5 Objects 类

5.1 概述

tips:理解内容

查看 API 文档,咱们能够看到 API 文档中对于 Objects 类的定义如下:

Objects 类所在包是在 java.util 包下,因而在应用的时候须要进行导包。并且 Objects 类是被 final 润饰的,因而该类不能被继承。

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

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

咱们能够发现 Objects 类中无无参构造方法,因而咱们不能应用 new 关键字去创立 Objects 的对象。同时咱们能够发现 Objects 类中所提供的办法都是动态的。因而咱们能够通过类名间接去调用这些办法。

5.2 常见办法

tips:重点解说内容

<font color=”red” size=”3″>常见办法介绍</font>

咱们要重点学习的 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 类型。

<font color=”red” size=”3″>案例演示</font>

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

<font color=”blue” size=”2″>案例 1 </font>:演示重点学习办法

实现步骤:

  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("itheima" , "14") ;

        // 调用 Objects 类中的 nonNull 办法
        boolean result = Objects.nonNull(s1);

        // 输入后果
        System.out.println(result);

    }

    // 测试 isNull 办法
    public static void method_03() {

        // 创立一个学生对象
        Student s1 = new Student("itheima" , "14") ;

        // 调用 Objects 类中的 isNull 办法
        boolean result = Objects.isNull(s1);

        // 输入后果
        System.out.println(result);

    }

    // 测试 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);

    }

    // 测试 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);

    }

}

<font color=”blue” size=”2″>案例 2 </font>:演示须要理解的办法

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);

    }

    // 演示 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 常见办法

<font color=”red” size=”3″>构造方法</font>

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 对象

<font color=”red” size=”3″>常见成员办法</font>

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

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 常见办法

<font color=”red” size=”3″>构造方法</font>

要用 BigDecimal 类,那么就须要首先学习一下如何去创立 BigDecimal 的对象。通过查看 API 文档,咱们能够发现 Jdk 中针对 BigDecimal 类提供了很多的构造方法,然而最罕用的构造方法是:

理解完常见的构造方法当前,咱们接下来就重点介绍一下常见的成员办法。

<font color=”red” size=”3″>常见成员办法</font>

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

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

接下来咱们就来通过一些案例演示一下这些成员办法的应用。

<font color=”blue” size=”2″>案例 1 </font>:演示根本的四则运算

代码如下所示:

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 类来实现浮点数的计算不会存在损失精度的问题。

<font color=”blue” size=”2″>案例 2 </font>:演示除法的非凡状况

如果应用 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 码表上的值,都存储到数组中。

正文完
 0