JAVA学习笔记 12 - 包装类和数字处理

本文是Java基础课程的第十二课。本文主要介绍Java中包装类的概念及使用,Java针对数字处理所提供的一些常用的类库,如java.text.NumberFormat、java.lang.Math、java.math.BigInteger等等

文章目录

  • 一、Java中的包装类
    • 1、什么是包装类
    • 2、包装类的实例化
    • 3、包装类的作用
    • 4、自动装箱和自动拆箱
  • 二、常见的数字处理类
    • 1、java.text.NumberFormat
    • 2、java.text.DecimalFormat
    • 3、java.lang.Math
    • 4、java.math.BigInteger
    • 5、java.math.BigDecimal

一、Java中的包装类

1、什么是包装类

关于Java中包装类的知识在之前的章节中已经提到过,这里对包装类进行进一步的理解、巩固。

Java是一种面向对象的编程语言,但是Java中的基本数据类型不是面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,Java为每个基本数据类型设计了一个对应的类,这些和基本数据类型一一对应(共8个)统称为包装类(Wrapper Class)。包装类位于java.lang包下包装类基本数据类型对应关系如下表所示:

基本数据类型 引用数据类型
boolean java.lang.Boolean
char java.lang.Character
byte java.lang.Byte
short java.lang.Short
int java.lang.Integer
long java.lang.Lang
float java.lang.Float
double java.lang.Double

在这八个包装类中,java.lang.Characterjava.lang.Integer类外其他六个类类名和其所对应基本数据类型一致,只是类名第一个字母大写了。

在这些包装类中,表示数字的包装类都继承了java.lang.Number类,如图:
JAVA学习笔记 12 - 包装类和数字处理_第1张图片

2、包装类的实例化

Java中,实例化包装类的对象非常方便,这里介绍几种常用的方式。

其一,通过使用new关键字实例化对象
下面是一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // 通过new关键字实例化一些包装类的对象
        Boolean boolean1 = new Boolean(true);
        Boolean boolean2 = new Boolean("随便");
        Character character1 = new Character('a');
        Byte byte1 = new Byte((byte)1); // 构造方法需要的参数为byte类型,字面量1为int类型,需要强制类型转换
        Byte byte2 = new Byte("1");
        Short short1 = new Short((short)2); // 构造方法需要的参数为short类型,字面量2为int类型,需要强制类型转换
        Short short2 = new Short("2");
        Integer integer1 = new Integer(3);
        Integer integer2 = new Integer("3");
        Long long1 = new Long(4); // 构造方法需要的参数为long类型,字面量4为int类型,这里自动类型转换了
        Long long2 = new Long("4");
        Float float1 = new Float(5.0f); // 这里使用new Float(5.0)也是可以的,Float类提供了以double类型作为参数的构造方法
        Float float2 = new Float("5.0");
        Double double1 = new Double(6.0);
        Double double2 = new Double("6.0");
        // 打印这些包装类对象
        System.out.println("boolean1 = " + boolean1);
        System.out.println("boolean2 = " + boolean2);
        System.out.println("character1 = " + character1);
        System.out.println("byte1 = " + byte1);
        System.out.println("byte2 = " + byte2);
        System.out.println("short1 = " + short1);
        System.out.println("short2 = " + short2);
        System.out.println("integer1 = " + integer1);
        System.out.println("integer2 = " + integer2);
        System.out.println("long1 = " + long1);
        System.out.println("long2 = " + long2);
        System.out.println("float1 = " + float1);
        System.out.println("float2 = " + float2);
        System.out.println("double1 = " + double1);
        System.out.println("double2 = " + double2);
    }
}

执行输出结果:

boolean1 = true
boolean2 = false
character1 = a
byte1 = 1
byte2 = 1
short1 = 2
short2 = 2
integer1 = 3
integer2 = 3
long1 = 4
long2 = 4
float1 = 5.0
float2 = 5.0
double1 = 6.0
double2 = 6.0

说明:

  • 本例演示了通过使用new关键字实例化各包装类的对象。
  • 除了java.lang.Character类外,其他包装类都至少提供了两个构造方法,其中一个使用基本数据类型的值作为参数,另一个使用字符串作为参数。
  • 对于java.lang.Boolean类型,其以字符串作为参数的构造方法当传入的参数为"true"(不区分大小写)时,实例化出的对象代表true,而是用其它字符串作为参数时,实例化出的对象均代表false
  • 通过观察各包装类对象的打印结果,不难发现,各包装类中的toString()方法均已被重写。

其二,通过各包装类中重载过的valueOf()方法获得实例化的对象
下面是一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // 通过各包装类的重载的valueOf()方法获取一些包装类的对象
        Boolean boolean1 = Boolean.valueOf(true);
        Boolean boolean2 = Boolean.valueOf("随便");
        Character character1 = Character.valueOf('c');
        Byte byte1 = Byte.valueOf((byte)1); // valueOf(byte b)方法需要的参数为byte类型,字面量1为int类型,需要强制类型转换
        Byte byte2 = Byte.valueOf("1");
        Short short1 = Short.valueOf((short)2); // valueOf(short s)方法需要的参数为short类型,字面量2为int类型,需要强制类型转换
        Short short2 = Short.valueOf("2");
        Integer integer1 = Integer.valueOf(3);
        Integer integer2 = Integer.valueOf("3");
        Long long1 = Long.valueOf(4); //  valueOf(long l)方法需要的参数为long类型,字面量4为int类型,这里自动类型转换了
        Long long2 = Long.valueOf("4");
        Float float1 = Float.valueOf(5.0f);
        Float float2 = Float.valueOf("5.0");
        Double double1 = Double.valueOf(6.0);
        Double double2 = Double.valueOf("6.0");
        // 打印这些包装类对象
        System.out.println("boolean1 = " + boolean1);
        System.out.println("boolean2 = " + boolean2);
        System.out.println("character1 = " + character1);
        System.out.println("byte1 = " + byte1);
        System.out.println("byte2 = " + byte2);
        System.out.println("short1 = " + short1);
        System.out.println("short2 = " + short2);
        System.out.println("integer1 = " + integer1);
        System.out.println("integer2 = " + integer2);
        System.out.println("long1 = " + long1);
        System.out.println("long2 = " + long2);
        System.out.println("float1 = " + float1);
        System.out.println("float2 = " + float2);
        System.out.println("double1 = " + double1);
        System.out.println("double2 = " + double2);
    }
}

执行输出结果:

boolean1 = true
boolean2 = false
character1 = c
byte1 = 1
byte2 = 1
short1 = 2
short2 = 2
integer1 = 3
integer2 = 3
long1 = 4
long2 = 4
float1 = 5.0
float2 = 5.0
double1 = 6.0
double2 = 6.0

说明:

  • 本例演示了通过各包装类中重载过的valueOf()方法获得实例化的对象。
  • 除了java.lang.Character类外,其他包装类都至少提供了两个重载的valueOf()方法,其中一个使用基本数据类型的值作为参数,另一个使用字符串作为参数。
  • 对于java.lang.Boolean类型,其valueOf(String s)方法当传入的参数为"true"(不区分大小写)时,实例化出的对象代表true,而是用其它字符串作为参数时,实例化出的对象均代表false

下面是另一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
    	// 通过valueOf(int i)方法获取一些Integer类的对象
        Integer integer1 = Integer.valueOf(100);
        Integer integer2 = Integer.valueOf(100);
        Integer integer3 = Integer.valueOf(128);
        Integer integer4 = Integer.valueOf(128);
        
        // == 操作符比较
        System.out.println("(integer1 == integer2) = " + (integer1 == integer2));
        System.out.println("(integer3 == integer4) = " + (integer3 == integer4));
        
        // equals(Object obj)方法比较
        System.out.println("integer1.equals(integer2) = " + integer1.equals(integer2));
        System.out.println("integer3.equals(integer4) = " + integer3.equals(integer4));
    }
}

执行输出结果:

(integer1 == integer2) = true
(integer3 == integer4) = false
integer1.equals(integer2) = true
integer3.equals(integer4) = true

说明:

  • 观察本例,变量integer1integer2都是通过java.lang.Integer类的静态方法valueOf(int i)获得的,包装的数字都是100,使用==操作符比较变量integer1integer2,得到的结果是true;变量integer3integer4同样都是通过java.lang.Integer类的静态方法valueOf(int i)获得的,只不过包装的数字都是128,使用==操作符比较它们时,得到的结果却是false。本质上,变量integer1integer2引用了同一块内存地址编号,而变量integer3integer4则分别引用了不同的内存地址编号。产生这种现象的原因是,java.lang.Integer类中包含一个静态成员内部类IntegerCache,该类中有一个java.lang.Integer类型的数组cache,该数组中保存着一系列的java.lang.Integer类对象,依次包装了从-128127(默认)这一范围内的数字,作为缓存。当使用valueOf(int i)获取java.lang.Integer类对象时,会先判断前述的缓存中是否有对应的对象,有则直接返回,没有则实例化一个新的java.lang.Integer类对象返回。包装类java.lang.Characterjava.lang.Bytejava.lang.Shortjava.lang.Long中都有类似的机制。
  • 如果要比较包装类对象所包装的值是否相同,需要使用equals(Object obj)方法。各包装类的equals(Object obj)方法均已被重写。

其三,直接使用基本数据类型字面量赋值获得包装类对象
下面是一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // 使用基本数据类型的字面量值赋值,获得包装类对象
        Boolean boolean1 = true;
        Character character1 = 'c';
        Byte byte1 = 1;
        Short short1 = 2;
        Integer integer1 = 3;
        Long long1 = 4L;
        Float float1 = 5.0f;
        Double double1 = 6.0;
        // 打印这些包装类对象
        System.out.println("boolean1 = " + boolean1);
        System.out.println("character1 = " + character1);
        System.out.println("byte1 = " + byte1);
        System.out.println("short1 = " + short1);
        System.out.println("integer1 = " + integer1);
        System.out.println("long1 = " + long1);
        System.out.println("float1 = " + float1);
        System.out.println("double1 = " + double1);
    }
}

执行输出结果:

boolean1 = true
character1 = c
byte1 = 1
short1 = 2
integer1 = 3
long1 = 4
float1 = 5.0
double1 = 6.0

说明:

  • 本例演示了直接使用基本数据类型的字面量值赋值,获得包装类对象。这也是最常用的方法。

3、包装类的作用

Java中,包装类有许多用途。这里介绍最常见的一些用途。

其一,包装类包含对应基本数据类型相关属性如最大值、最小值等,以及相关操作方法
下面是一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // byte
        System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE);
        System.out.println("包装类:java.lang.Byte");
        System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);
        System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE);
        System.out.println();

        // short
        System.out.println("基本类型:short 二进制位数:" + Short.SIZE);
        System.out.println("包装类:java.lang.Short");
        System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE);
        System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE);
        System.out.println();

        // int
        System.out.println("基本类型:int 二进制位数:" + Integer.SIZE);
        System.out.println("包装类:java.lang.Integer");
        System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE);
        System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE);
        System.out.println();

        // long
        System.out.println("基本类型:long 二进制位数:" + Long.SIZE);
        System.out.println("包装类:java.lang.Long");
        System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE);
        System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE);
        System.out.println();

        // float
        System.out.println("基本类型:float 二进制位数:" + Float.SIZE);
        System.out.println("包装类:java.lang.Float");
        System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE);
        System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE);
        System.out.println();

        // double
        System.out.println("基本类型:double 二进制位数:" + Double.SIZE);
        System.out.println("包装类:java.lang.Double");
        System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE);
        System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE);
        System.out.println();

        // char
        System.out.println("基本类型:char 二进制位数:" + Character.SIZE);
        System.out.println("包装类:java.lang.Character");
        // 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台
        System.out.println("最小值:Character.MIN_VALUE=" + (int) Character.MIN_VALUE);
        // 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台
        System.out.println("最大值:Character.MAX_VALUE=" + (int) Character.MAX_VALUE);
    }
}

执行输出结果:

基本类型:byte 二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127

基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767

基本类型:int 二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647

基本类型:long 二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807

基本类型:float 二进制位数:32
包装类:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38

基本类型:double 二进制位数:64
包装类:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308

基本类型:char 二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535

说明:

  • 本例演示了通过包装类获取对应基本数据类型的相关属性,如最大值、最小值等。这在之前的章节中已经演示过,不再赘述。

下面是另一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // 通过包装类对象获取对应其他基本类型的值
        Short num1 = 1;
        byte num2 = num1.byteValue();
        System.out.println("num2 = " + num2);
        Integer num3 = 25;
        float num4 = num3.floatValue();
        System.out.println("num4 = " + num4);

        // 比较两个基本类型的大小
        int num5 = 12, num6 = 21;
        int max = Integer.max(num5, num6);
        System.out.println("max = " + max);
        int min = Integer.min(num5, num6);
        System.out.println("min = " + min);

        // 获取2进制、8进制、16进制表示的字符串
        int num7 = 100;
        String binaryString = Integer.toBinaryString(num7);
        System.out.println("binaryString = " + binaryString);
        String octalString = Integer.toOctalString(num7);
        System.out.println("octalString = " + octalString);
        String hexString = Integer.toHexString(num7);
        System.out.println("hexString = " + hexString);

        // 两个基本类型的加法
        double num8 = 13.5, num9 = 30.8;
        double sum = Double.sum(num8, num9);
        System.out.println("sum = " + sum);
    }
}

执行输出结果:

num2 = 1
num4 = 25.0
max = 21
min = 12
binaryString = 1100100
octalString = 144
hexString = 64
sum = 44.3

说明:

  • 本例演示了包装类中提供的一些基本的关于数字处理的方法,如数字类型之间的转换、数字比较、数字在不同进制之间的转换等。
  • 本例中的演示过的byteValue()方法、floatValue()方法均继承自java.lang.Number类。java.lang.Number类中提供了一些常用API大多是抽象的,方便各包装类重写后用于获取对应的各种基本数据类型,这些API如下:
    方法 返回值类型 方法说明
    byteValue() byte 返回该Number对象封装的数字,作为一个byte类型的值,这可能涉及舍入或截断
    shortValue() short 返回该Number对象封装的数字,作为一个short类型的值,这可能涉及舍入或截断
    intValue() int 返回该Number对象封装的数字,作为一个int类型的值,这可能涉及舍入或截断
    longValue() long 返回该Number对象封装的数字,作为一个long类型的值,这可能涉及舍入或截断
    floatValue() float 返回该Number对象封装的数字,作为一个float类型的值,这可能涉及舍入
    doubleValue() double 返回该Number对象封装的数字,作为一个double类型的值,这可能涉及舍入

其二、字符串String转换基本数据类型,需要借助包装类
下面是一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // 通过各包装类的parseXXX()方法将字符串转换为基本数据类型
        byte num1 = Byte.parseByte("1");
        short num2 = Short.parseShort("2");
        int num3 = Integer.parseInt("3");
        long num4 = Long.parseLong("4");
        float num5 = Float.parseFloat("5.0");
        double num6 = Double.parseDouble("6.0");
        boolean boolean1 = Boolean.parseBoolean("true");
        boolean boolean2 = Boolean.parseBoolean("随便");
        // char类型直接使用字符串的charAt(int index)方法
        char char1 = "hello world".charAt(1);

        // 打印
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
        System.out.println("num3 = " + num3);
        System.out.println("num4 = " + num4);
        System.out.println("num5 = " + num5);
        System.out.println("num6 = " + num6);
        System.out.println("boolean1 = " + boolean1);
        System.out.println("boolean2 = " + boolean2);
        System.out.println("char1 = " + char1);
    }
}

执行输出结果:

num1 = 1
num2 = 2
num3 = 3
num4 = 4
num5 = 5.0
num6 = 6.0
boolean1 = true
boolean2 = false
char1 = e

说明:

  • 关于使用包装类将字符串(String)转换为基本数据类型,在之前关于字符串的章节中已经介绍,这里不再赘述。
  • 需要注意的是,在将字符串(String)转换为基本数据类型的过程中,如果字符串本身无法转换,会抛出NumberFormatException异常,这是一个运行时异常。对于除了"true"以为的任意字符串或null,使用Boolean.parseBoolean(String s)方法获得的布尔值都将是false
  • 细心的开发者应该发现,在前文中包装类的实例化这一小节内容中,各包装类中均有重载的构造方法及重载的valueOf()方法可以将字符串当作参数,事实上,这些方法内部都在调用各包装类对应的parseXXX()方法,先将字符串转换为基本数据类型的值,然后再实例化包装类的对象。

其三、作为基本数据类型对应引用类型存在方便涉及对象操作。这一方面的作用在后续的章节中将会看到。

4、自动装箱和自动拆箱

装箱的含义是,将基本数据类型封装为包装类对象拆箱的含义是,将包装类中包装的基本数据类型数据取出自动装箱自动拆箱装箱和拆箱过程都是自发完成的。

自动装箱自动拆箱是一种编译器机制自动装箱本质上是在编译过程中,在需要装箱的地方调用各包装类对应的valueOf()方法,而自动拆箱本质上是在编译过程中,在需要拆箱的地方调用各包装类对应的xxxValue()方法(如Integer类的对象在自动拆箱时会调用intValue()方法,Float类的对象在自动拆箱时会调用floatValue()方法)。

下面是一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // 直接使用基本数据类型的字面量值赋值,获得包装类对象,就是一种自动装箱的过程
        Byte byte1 = 8;

        // 将一个包装类对象直接赋值给一个基本数据类型的变量,会自动拆箱
        Integer integer1 = new Integer(1);
        int num1 = integer1;

        // 一个包装类对象与一个基本数据类型的数值进行+运算,包装类对象也会被自动拆箱
        Float float1 = new Float(1.5f);
        float num2 = 1 + float1;
    }
}

说明:

  • 直接使用基本数据类型的字面量值赋值,获得包装类对象,就是一种自动装箱的过程。本例中的代码Byte byte1 = 8编译后对应的代码为Byte byte1 = Byte.valueOf(8)
  • 将一个包装类对象直接赋值给一个基本数据类型的变量,会自动拆箱。本例中的代码int num1 = integer1编译后对应的代码为int num1 = integer1.intValue()
  • 一个包装类对象与一个基本数据类型的数值使用+-*\==等操作符进行运算时,包装类对象也会被自动拆箱。本例中的代码float num2 = 1 + float1编译后对应的代码为float num2 = 1 + float1.floatValue()

二、常见的数字处理类

Java中提供了丰富的类库,帮助开发人员进行数学运算数字格式化等与数字处理有关的操作。

1、java.text.NumberFormat

在JDK提供的java.text包下,有一个NumberFormat,该类提供了丰富的数字格式化方法,是一个常用的数字处理类。
常用API如下:

方法 返回值类型 方法说明
getInstance() NumberFormat 返回当前默认区域的通用数字格式实例
getInstance(Locale inLocale) NumberFormat 返回指定区域设置的通用数字格式
getIntegerInstance() NumberFormat 返回当前默认的整数数字格式实例
getAvailableLocales() Locale[] 返回一个所有可用区域的数组
getCurrencyInstance() NumberFormat 返回当前默认区域的货币数字格式实例
getCurrencyInstance(Locale inLocale) NumberFormat 返回指定区域设置的货币数字格式
getPercentInstance() NumberFormat 返回当前默认区域的百分比数字格式实例
getPercentInstance(Locale inLocale) NumberFormat 返回指定区域设置的百分比数字格式
format(long number) String 数字格式化
format(double number) String 数字格式化

下面是一个示例:

package com.codeke.java.test;

import java.text.NumberFormat;
import java.util.Locale;

public class Test {
    public static void main(String[] args) {
        // 声明两个数字变量并初始化
        int num1 = 108732965;
        double num2 = 6314296.1816;

        // 测试各种形式的数字格式化
        // 通用数字格式
        NumberFormat nf1 = NumberFormat.getInstance();
        System.out.println("nf1.format(num1) = " + nf1.format(num1));
        System.out.println("nf1.format(num2) = " + nf1.format(num2));

        NumberFormat nf2 = NumberFormat.getInstance(Locale.US);
        System.out.println("nf2.format(num1) = " + nf2.format(num1));
        System.out.println("nf2.format(num2) = " + nf2.format(num2));

		// 货币数字格式
        NumberFormat nf3 = NumberFormat.getCurrencyInstance();
        System.out.println("nf3.format(num1) = " + nf3.format(num1));
        System.out.println("nf3.format(num2) = " + nf3.format(num2));

        NumberFormat nf4 = NumberFormat.getCurrencyInstance(Locale.US);
        System.out.println("nf4.format(num1) = " + nf4.format(num1));
        System.out.println("nf4.format(num2) = " + nf4.format(num2));

		// 百分比数字格式
        NumberFormat nf5 = NumberFormat.getPercentInstance();
        System.out.println("nf5.format(num1) = " + nf5.format(num1));
        System.out.println("nf5.format(num2) = " + nf5.format(num2));

        NumberFormat nf6 = NumberFormat.getPercentInstance(Locale.US);
        System.out.println("nf6.format(num1) = " + nf6.format(num1));
        System.out.println("nf6.format(num2) = " + nf6.format(num2));
    }
}

执行输出结果:

`nf1.format(num1) = 108,732,965
nf1.format(num2) = 6,314,296.182
nf2.format(num1) = 108,732,965
nf2.format(num2) = 6,314,296.182
nf3.format(num1) =108,732,965.00
nf3.format(num2) =6,314,296.18
nf4.format(num1) = $108,732,965.00
nf4.format(num2) = $6,314,296.18
nf5.format(num1) = 10,873,296,500%
nf5.format(num2) = 631,429,618%
nf6.format(num1) = 10,873,296,500%
nf6.format(num2) = 631,429,618%``

说明:

  • java.text.NumberFormat类是一个抽象类,通过该类的各种getXXXInstance方法获得的数字格式对象事实上都是其派生类的对象。
  • java.text.NumberFormat类在获得各种数字格式对象时,可以使用java.util.Locale来指定区域,可用的区域在java.util.Locale类中均已经被声明为常量。

2、java.text.DecimalFormat

开发人员在使用java.text.NumberFormat类来进行数字格式化时,大多数情况下其实是在使用java.text.DecimalFormat对象,开发人员也可以直接使用java.text.DecimalFormat的对象来实现更加灵活数字格式化操作。

下面是一个示例:

package com.codeke.java.test;

import java.text.DecimalFormat;

public class Test {
    public static void main(String[] args) {
        // 声明两个数字变量并初始化
        int num1 = 108732965;
        double num2 = 6314296.1816;

        // 实例化多个DecimalFormat类的实例
        DecimalFormat df1 = new DecimalFormat();
        DecimalFormat df2 = new DecimalFormat("#,####");
        DecimalFormat df3 = new DecimalFormat("#,###.000");
        DecimalFormat df4 = new DecimalFormat("0.##E0");
        DecimalFormat df5 = new DecimalFormat("#,###.00%");

        // 格式化并打印
        System.out.println("df1.format(num1) = " + df1.format(num1));
        System.out.println("df1.format(num2) = " + df1.format(num2));
        System.out.println("df2.format(num1) = " + df2.format(num1));
        System.out.println("df2.format(num2) = " + df2.format(num2));
        System.out.println("df3.format(num1) = " + df3.format(num1));
        System.out.println("df3.format(num2) = " + df3.format(num2));
        System.out.println("df4.format(num1) = " + df4.format(num1));
        System.out.println("df4.format(num2) = " + df4.format(num2));
        System.out.println("df5.format(num1) = " + df5.format(num1));
        System.out.println("df5.format(num2) = " + df5.format(num2));
    }
}

执行输出结果:

df1.format(num1) = 108,732,965
df1.format(num2) = 6,314,296.182
df2.format(num1) = 1,0873,2965
df2.format(num2) = 631,4296
df3.format(num1) = 108,732,965.000
df3.format(num2) = 6,314,296.182
df4.format(num1) = 1.09E8
df4.format(num2) = 6.31E6
df5.format(num1) = 10,873,296,500.00%
df5.format(num2) = 631,429,618.16%

说明:

  • 实例化java.text.DecimalFormat类的对象时,可以使用无参构造方法,获得的对象使用默认格式化样式;也可以使用含参构造方法指定格式化样式。指定格式化样式时,需要使用格式符,常用的格式符如下:
    格式符 说明
    # 代表一个数字位置,如果该位置没有数字,则不会显示
    , 代表数字中的分隔符
    0 代表一个数字位置,如果该位置没有数字,则用0来补充,小数中多余部分四舍五入
    . 表示小数点
    E 科学记数法
    % 用百分数表示数字

3、java.lang.Math

java.lang包下,JDK提供了Math。该类中提供了大量和基本数学运算相关方法常量,方法如加减乘除指数对数平方根三角函数等,常量最主要的两个是Math.EMath.PI,分表示自然对数的底数圆周率。该类中用于基本数学运算的方法均静态成员方法,直接用类名调用,使用非常方便。

java.lang.Math类中的常用API如下:

方法 返回值类型 方法说明
abs(int a) int 返回绝对值
abs(long a) long 返回绝对值
abs(float a) float 返回绝对值
abs(double a) double 返回绝对值
sin(double a) double 求指定double类型参数的正弦值
cos(double a) double 求指定double类型参数的余弦值
tan(double a) double 求指定double类型参数的正切值
asin(double a) double 求指定double类型参数的反正弦值
acos(double a) double 求指定double类型参数的反余弦值
atan(double a) double 求指定double类型参数的反正切值
toRadians(double angdeg) double 将角度转换为弧度
toDegrees(double angrad) double 将参数转化为角度
exp(double a) double 返回自然数底数e的参数次方
log(double a) double 返回参数的自然底数的对数值
log10(double a) double 返回参数的以10为底数的对数值
sqrt(double a) double 求参数的算术平方根
pow(double a, double b) double 返回第一个参数的第二个参数次方
addExact(int x, int y) int 返回其参数的总和,结果溢出则抛出异常
addExact(long x, long y) long 返回其参数的总和,结果溢出则抛出异常
incrementExact(int a) int 返回参数自增1的结果,结果溢出则抛出异常
incrementExact(long a) long 返回参数自增1的结果,结果溢出则抛出异常
subtractExact(int x, int y) int 返回参数的差,结果溢出则抛出异常
subtractExact(long x, long y) long 返回参数的差,结果溢出则抛出异常
decrementExact(int a) int 返回参数自减1的结果,结果溢出则抛出异常
decrementExact(long a) long 返回参数自减1的结果,结果溢出则抛出异常
multiplyExact(int x, int y) int 返回参数的乘积,结果溢出则抛出异常
multiplyExact(long x, long y) long 返回参数的乘积,结果溢出则抛出异常
max(double a, double b) double 返回参数中的较大值
max(float a, float b) float 返回参数中的较大值
max(int a, int b) int 返回参数中的较大值
max(long a, long b) long 返回参数中的较大值
min(double a, double b) double 返回参数中的较小值
min(float a, float b) float 返回参数中的较小值
min(int a, int b) int 返回参数中的较小值
min(long a, long b) long 返回参数中的较小值
random() double 随机返回一个[0.0, 1.0)区间内的double
ceil(double a) double 返回大于或等于参数的最小 double值,等于一个数学整数
floor(double a) double 返回小于或等于参数的最大 double值,等于一个数学整数
round(float a) int 返回最接近参数的int
round(double a) long 返回最接近参数的long

下面是一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        // 测试Math类中的常用方法
        // 绝对值
        System.out.println("Math.abs(-1314) = " + Math.abs(-1314));
        // 正弦
        System.out.println("Math.sin(Math.toRadians(30)) = " + Math.sin(Math.toRadians(30)));
        // 以e为底数,100的对数
        System.out.println("Math.log(100) = " + Math.log(100));
        // 以10为底数,100的对数
        System.out.println("Math.log10(100) = " + Math.log10(100));
        // 算数平方根
        System.out.println("Math.sqrt(3) = " + Math.sqrt(3));
        // 幂
        System.out.println("Math.pow(2,4) = " + Math.pow(2, 4));
        // 加
        System.out.println("Math.addExact(12, 13) = " + Math.addExact(12, 13));
        // 减
        System.out.println("Math.subtractExact(13, 7) = " + Math.subtractExact(13, 7));
        // 乘
        System.out.println("Math.multiplyExact(25,8) = " + Math.multiplyExact(25, 8));
        // 最大值
        System.out.println("Math.max(15, 32) = " + Math.max(15, 32));
        // 最小值
        System.out.println("Math.min(15, 32) = " + Math.min(15, 32));
        // [0.0, 1.0)区间内的随机数
        System.out.println("Math.random() = " + Math.random());
    }
}

执行输出结果:

Math.abs(-1314) = 1314
Math.sin(Math.toRadians(30)) = 0.49999999999999994
Math.log(100) = 4.605170185988092
Math.log10(100) = 2.0
Math.sqrt(3) = 1.7320508075688772
Math.pow(2,4) = 16.0
Math.addExact(12, 13) = 25
Math.subtractExact(13, 7) = 6
Math.multiplyExact(25,8) = 200
Math.max(15, 32) = 32
Math.min(15, 32) = 15
Math.random() = 0.36067650327439227

说明:

  • 本例测试了java.lang.Math类中的abs(int a)sin(double a)log(double a)sqrt(double a)pow(double a, double b)addExact(int x, int y)max(int a, int b)random()等方法,使用都非常简单,这里不再赘述。

下面是另一个示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        double[] nums = {1.4, 1.5, 1.6, -1.4, -1.5, -1.6};
        for (double num : nums) {
            test(num);
        }
    }

    private static void test(double num) {
        // 测试Math类中的ceil(double a)、floor(double a)、round(double a)方法
        System.out.println("Math.ceil(" + num + ")=" + Math.ceil(num));
        System.out.println("Math.floor(" + num + ")=" + Math.floor(num));
        System.out.println("Math.round(" + num + ")=" + Math.round(num));
    }
}

执行输出结果:

Math.ceil(1.4)=2.0
Math.floor(1.4)=1.0
Math.round(1.4)=1
Math.ceil(1.5)=2.0
Math.floor(1.5)=1.0
Math.round(1.5)=2
Math.ceil(1.6)=2.0
Math.floor(1.6)=1.0
Math.round(1.6)=2
Math.ceil(-1.4)=-1.0
Math.floor(-1.4)=-2.0
Math.round(-1.4)=-1
Math.ceil(-1.5)=-1.0
Math.floor(-1.5)=-2.0
Math.round(-1.5)=-1
Math.ceil(-1.6)=-1.0
Math.floor(-1.6)=-2.0
Math.round(-1.6)=-2

说明:

  • 本例测试了java.lang.Math类中的ceil(double a)floor(double a)round(double a)方法,请注意比较它们的区别。

4、java.math.BigInteger

Java中,基本数据类型中可以表示的整型数字最大范围64位long型整数),如果程序中所需要使用的整数范围超过long最大范围,就需要使用java.math.BigInteger来处理。java.math.BigInteger可以用来表示任意大小整数

实例化一个java.math.BigInteger类的对象时,需要使用new关键字,该类提供了几个常用构造方法,如下:

构造方法 构造方法说明
BigInteger(String val) BigInteger的十进制字符串表示形式转换为 BigInteger实例
BigInteger(String val, int radix) 将指定基数的 BigInteger的字符串表示形式转换为 BigInteger实例
BigInteger(byte[] val) 将包含 BigInteger的二进制补码表示形式的 byte数组转换为 BigInteger实例

下面是一个示例:

package com.codeke.java.test;

import java.math.BigInteger;

public class Test {
    public static void main(String[] args) {
        // 实例化BigInteger对象
        BigInteger bigInteger1 = new BigInteger("123456789123456789123456789");
        BigInteger bigInteger2 = new BigInteger(new byte[]{127,1,1,1});
        BigInteger bigInteger3 = new BigInteger("123456789123456789123456789",10);
        BigInteger bigInteger4 = new BigInteger("01111111000000010000000100000001",2);
        // 打印它们的值
        System.out.println("bigInteger1 = " + bigInteger1);
        System.out.println("bigInteger2 = " + bigInteger2);
        System.out.println("bigInteger3 = " + bigInteger3);
        System.out.println("bigInteger4 = " + bigInteger4);
    }
}

执行输出结果:

bigInteger1 = 123456789123456789123456789
bigInteger2 = 2130772225
bigInteger3 = 123456789123456789123456789
bigInteger4 = 2130772225

说明:

  • 本例演示了java.math.BigInteger类的几种常用构造方法。java.math.BigInteger类的对象可以表示任意大小的整数。

对于java.math.BigInteger类对象的基本算数运算等操作,需要使用该类的实例成员方法。该类中常用API如下:

方法 返回值类型 方法说明
abs() BigInteger 返回此BigInteger实例的绝对值
add(BigInteger val) BigInteger 返回值为 (this + val) 的BigInteger实例
subtract(BigInteger val) BigInteger 返回值为 (this - val) 的BigInteger实例
multiply(BigInteger val) BigInteger 返回值为 (this * val) 的BigInteger实例
divide(BigInteger val) BigInteger 返回值为 (this / val) 的BigInteger实例
mod(BigInteger m) BigInteger 返回值为 (this mod m) 的BigInteger实例
remainder(BigInteger val) BigInteger 返回值为 (this % val) 的BigInteger实例
pow(int exponent) BigInteger 返回值为 thisexponent次幂的BigInteger实例
max(BigInteger val) BigInteger 返回thisval中值较大的一个
min(BigInteger val) BigInteger 返回thisval中值较小的一个
toString() String 返回此BigInteger的十进制字符串表示形式
toString(int radix) String 返回给定基数中BigInteger的字符串表示形式

下面是一个示例:

package com.codeke.java.test;

import java.math.BigInteger;

public class Test {
    public static void main(String[] args) {
        // 实例化BigInteger类对象
        BigInteger num1 = new BigInteger("123456789123456789");
        BigInteger num2 = new BigInteger("987654321987654321");
        // 测试BigInteger类常用的方法
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
        System.out.println("num1.abs() = " + num1.abs());
        System.out.println("num1.add(num2) = " + num1.add(num2));
        System.out.println("num2.subtract(num1) = " + num2.subtract(num1));
        System.out.println("num1.multiply(num2) = " + num1.multiply(num2));
        System.out.println("num2.divide(num1) = " + num2.divide(num1));
        System.out.println("num1.mod(num2) = " + num1.mod(num2));
        System.out.println("num1.remainder(num2) = " + num1.remainder(num2));
        System.out.println("num1.pow(num2) = " + num1.pow(2));
        System.out.println("num1.max(num2) = " + num1.max(num2));
        System.out.println("num1.min(num2) = " + num1.min(num2));
    }
}

执行输出结果:

num1 = 123456789123456789
num2 = 987654321987654321
num1.abs() = 123456789123456789
num1.add(num2) = 1111111111111111110
num2.subtract(num1) = 864197532864197532
num1.multiply(num2) = 121932631356500531347203169112635269
num2.divide(num1) = 8
num1.mod(num2) = 123456789123456789
num1.remainder(num2) = 123456789123456789
num1.pow(num2) = 15241578780673678515622620750190521
num1.max(num2) = 987654321987654321
num1.min(num2) = 123456789123456789

说明:

  • 本例演示了java.math.BigInteger类中abs()add(BigInteger val)subtract(BigInteger val)mod(BigInteger m)pow(int exponent)max(BigInteger val)等众多方法,java.math.BigInteger类的对象在进行加减乘除操作时,不会有范围限制,但是运算速度比起基本数据类型的运算来说会慢一些。

下面是另一个示例:

package com.codeke.java.test;

import java.math.BigInteger;

public class Test {
    public static void main(String[] args) {
        // // 实例化BigInteger类对象
        BigInteger num = new BigInteger("9223372036854775808");
        System.out.println("num1 = " + num);

        // 获取基本数据类型的值,不保证结果准确
        System.out.println("num.byteValue() = " + num.byteValue());
        System.out.println("num.shortValue() = " + num.shortValue());
        System.out.println("num.intValue() = " + num.intValue());
        System.out.println("num.longValue() = " + num.longValue());
        System.out.println("num.floatValue() = " + num.floatValue());
        System.out.println("num.doubleValue() = " + num.doubleValue());

        // 获取基本数据类型的值,转换时如果超出范围,将直接抛出ArithmeticException异常,保证结果是准确的
        try {
            System.out.println("num.byteValueExact() = " + num.byteValueExact());
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
        try {
            System.out.println("num.shortValueExact() = " + num.shortValueExact());
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
        try {
            System.out.println("num.intValueExact() = " + num.intValueExact());
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
        try {
            System.out.println("num.longValueExact() = " + num.longValueExact());
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }
}

执行输出结果:

num = 9223372036854775808
num.byteValue() = 0
num.shortValue() = 0
num.intValue() = 0
num.longValue() = -9223372036854775808
num.floatValue() = 9.223372E18
num.doubleValue() = 9.223372036854776E18
java.lang.ArithmeticException: BigInteger out of byte range
	at java.math.BigInteger.byteValueExact(BigInteger.java:4592)
	at com.codeke.java.test.Test.main(Test.java:21)
java.lang.ArithmeticException: BigInteger out of short range
	at java.math.BigInteger.shortValueExact(BigInteger.java:4571)
	at com.codeke.java.test.Test.main(Test.java:26)
java.lang.ArithmeticException: BigInteger out of int range
	at java.math.BigInteger.intValueExact(BigInteger.java:4550)
	at com.codeke.java.test.Test.main(Test.java:31)
java.lang.ArithmeticException: BigInteger out of long range
	at java.math.BigInteger.longValueExact(BigInteger.java:4531)
	at com.codeke.java.test.Test.main(Test.java:36)

说明:

  • java.math.BigInteger类同大多数包装类一样,继承自java.lang.Number类,故java.math.BigInteger类也继承并重写java.lang.Number类中用以获取各种基本数据类型对应数值方法。即byteValue()(未重写)、shortValue()(未重写)、intValue()longValue()floatValue()doubleValue()
  • 上述intValue()longValue()floatValue()doubleValue()方法在将java.math.BigInteger类的对象转换为基本数据类型时,均有可能出现java.math.BigInteger类对象表示的数字超过基本数据类型可以表示范围的情况,此时,转换时会丢失高位信息,转换结果不一定准确。如果需要准确地转换成基本类型,可以使用java.math.BigInteger提供的byteValueExact()shortValueExact()intValueExact()longValueExact()方法,这些方法在转换时如果超出范围,将直接抛出ArithmeticException异常

5、java.math.BigDecimal

先来看下面的示例:

package com.codeke.java.test;

public class Test {
    public static void main(String[] args) {
        System.out.println(0.05 + 0.01);
        System.out.println(1.0 - 0.42);
        System.out.println(4.015 * 100);
        System.out.println(123.3 / 100);
    }
}

执行输出结果:

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

说明:

  • 在Java中,使用基本数据类型(即float类型和double类型)的浮点数时,由于小数在转换为二进制时并不一定能用一个精确的二进制表示,大多数时候都是取一个近似值,这就造成了精度丢失。如果再用这个二进制进行计算,计算结果的精度会进一步丢失。

通过上例可以看到,使用基本数据类型进行浮点数处理时,极大可能存在精度丢失的风险,这在类似财务计算、地图位置经纬度计算等需要精准浮点数处理业务场景中,无法保证程序结果的准确性

针对上述问题,Java已经提供了解决方案,在Java中,和java.math.BigInteger类类似的,可以使用java.math.BigDecimal对象表示一个任意大小精度完全准确浮点数java.math.BigDecimal也同样继承自java.lang.Number

实例化java.math.BigDecimal的对象时常用构造方法如下:

构造方法 构造方法说明
BigDecimal(BigInteger val) 将一个BigInteger实例转换成一个BigDecimal实例
BigDecimal(BigInteger val, MathContext mc) 用一个BigInteger实例和指定的上下文获得一个BigDecimal实例
BigDecimal(BigInteger unscaledVal, int scale) 用一个BigInteger实例和一个指定的小数位数获得一个BigDecimal实例
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) 用一个BigInteger实例、一个指定的小数位数和指定的上下文获得一个BigDecimal实例
BigDecimal(double val) 用一个double值获得一个BigDecimal实例
BigDecimal(double val, MathContext mc) 用一个double值和指定的上下文获得一个BigDecimal实例
BigDecimal(int val) 用一个int值获得一个BigDecimal实例
BigDecimal(int val, MathContext mc) 用一个int值和指定的上下文获得一个BigDecimal实例
BigDecimal(long val) 用一个long值获得一个BigDecimal实例
BigDecimal(long val, MathContext mc) 用一个long值和指定的上下文获得一个BigDecimal实例
BigDecimal(String val) 用一个String对象表示的数字获得一个BigDecimal实例
BigDecimal(String val, MathContext mc) 用一个String对象表示的数字和指定的上下文获得一个BigDecimal实例

下面是一个示例:

package com.codeke.java.test;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;

public class Test {
    public static void main(String[] args) {
        // 实例化几个BigDecimal对象
        BigDecimal num1 = new BigDecimal(new BigInteger("123456"));
        BigDecimal num2 = new BigDecimal(new BigInteger("123456"), new MathContext(2, RoundingMode.CEILING));
        BigDecimal num3 = new BigDecimal(new BigInteger("123456"), 4);
        BigDecimal num4 = new BigDecimal(new BigInteger("123456"), 4, new MathContext(2, RoundingMode.FLOOR));
        BigDecimal num5 = new BigDecimal(123.456);
        BigDecimal num6 = new BigDecimal(123.456, new MathContext(3, RoundingMode.UP));
        BigDecimal num7 = new BigDecimal(123456);
        BigDecimal num8 = new BigDecimal(123456, new MathContext(3, RoundingMode.DOWN));
        BigDecimal num9 = new BigDecimal(123456L);
        BigDecimal num10 = new BigDecimal(123456L, new MathContext(4, RoundingMode.HALF_UP));
        BigDecimal num11 = new BigDecimal("123456");
        BigDecimal num12 = new BigDecimal("123456", new MathContext(4, RoundingMode.HALF_DOWN));

        // 打印
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
        System.out.println("num3 = " + num3);
        System.out.println("num4 = " + num4);
        System.out.println("num5 = " + num5);
        System.out.println("num6 = " + num6);
        System.out.println("num7 = " + num7);
        System.out.println("num8 = " + num8);
        System.out.println("num9 = " + num9);
        System.out.println("num10 = " + num10);
        System.out.println("num11 = " + num11);
        System.out.println("num12 = " + num12);
    }
}

执行输出结果:

num1 = 123456
num2 = 1.3E+5
num3 = 12.3456
num4 = 12
num5 = 123.4560000000000030695446184836328029632568359375
num6 = 124
num7 = 123456
num8 = 1.23E+5
num9 = 123456
num10 = 1.235E+5
num11 = 123456
num12 = 1.235E+5

说明:

  • 本例演示了java.math.BigDecimal常用构造方法部分构造方法需要传入一个java.math.MathContext实例作为构造数字的上下文==。java.math.MathContext类常用构造方法MathContext(int setPrecision, RoundingMode setRoundingMode),第一个参数指定了精度,第二个参数指定了舍入模式,而舍入模式由java.math.RoundingMode枚举指定,常见舍入模式有:
    舍入模式 说明
    CEILING 正无穷大方向舍入
    FLOOR 负无穷大方向舍入
    UP 正数向正无穷大舍入,负数向负无穷大舍入
    DOWN 0的方向舍入
    HALF_UP 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式
    HALF_DOWN 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向下舍入的舍入模式
    HALF_EVEN 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为同 RoundingMode.HALF_UP;如果为偶数,则舍入行为同 RoundingMode.HALF_DOWN
  • 需要注意的是,仍然由于基本数据类型浮点数转换为二进制时的精度丢失问题,使用BigDecimal(double val)构造方法获得的浮点数仍然会有精度丢失的情况,更好的办法是构造时使用上下文指定精度舍入模式进行控制,或者直接使用字符串String形式的数字来构造,再或者使用该类的valueOf(double val)方法获得实例,在valueOf(double val)方法中,会先将double类型值转换为字符串再进行构造

对于java.math.BigDecimal类对象的基本算数运算等操作,需要使用该类的实例成员方法。该类中常用API如下:

方法 返回值类型 方法说明
abs() BigDecimal 返回此BigDecimal实例的绝对值
abs(MathContext mc) BigDecimal 返回此BigDecimal实例的绝对值,并根据上下文进行舍入
add(BigDecimal augend) BigDecimal 返回值为 (this + augend) 的BigDecimal实例
add(BigDecimal augend, MathContext mc) BigDecimal 返回值为 (this + augend) 的BigDecimal实例,并根据上下文进行舍入
subtract(BigDecimal subtrahend) BigDecimal 返回值为 (this - subtrahend) 的BigDecimal实例
subtract(BigDecimal subtrahend, MathContext mc) BigDecimal 返回值为 (this - subtrahend) 的BigDecimal实例,并根据上下文进行舍入
multiply(BigDecimal multiplicand) BigDecimal 返回值为 (this * multiplicand) 的BigDecimal实例
multiply(BigDecimal multiplicand, MathContext mc) BigDecimal 返回值为 (this * multiplicand) 的BigDecimal实例,并根据上下文进行舍入
divide(BigDecimal divisor) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例
divide(BigDecimal divisor, int roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,并根据指定的舍入模式舍入
divide(BigDecimal divisor, RoundingMode roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,并根据指定的舍入模式舍入
divide(BigDecimal divisor, int scale, int roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,指定返回值的小数位数,并根据指定的舍入模式舍入
divide(BigDecimal divisor, int scale, RoundingMode roundingMode) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,指定返回值的小数位数,并根据指定的舍入模式舍入
divide(BigDecimal divisor, MathContext mc) BigDecimal 返回值为 (this / divisor) 的BigDecimal实例,并根据上下文进行舍入
remainder(BigDecimal divisor) BigDecimal 返回值为 (this % divisor) 的BigDecimal实例
pow(int n) BigDecimal 返回值为 thisn次幂的BigDecimal实例
pow(int n, MathContext mc) BigDecimal 返回值为 thisn次幂的BigDecimal实例,并根据上下文进行舍入
round(MathContext mc) BigDecimal BigDecimal实例按指定的上下文进行舍入
max(BigDecimal val) BigDecimal 返回thisval中值较大的一个
min(BigDecimal val) BigDecimal 返回thisval中值较小的一个
toString() String 返回此BigDecimal的十进制字符串表示形式
byteValueExact() byte 将此 BigDecimal实例转换为 byte值,转换时会进行检查
shortValueExact() short 将此 BigDecimal实例转换为 short值,转换时会进行检查
intValue() int 将此 BigDecimal实例转换为 int
intValueExact() int 将此 BigDecimal实例转换为 int值,转换时会进行检查
longValue() long 将此 BigDecimal实例转换为 long
longValueExact() long 将此 BigDecimal实例转换为 long值,转换时会进行检查
floatValue() float 将此 BigDecimal实例转换为 float
doubleValue() double 将此 BigDecimal实例转换为 double

下面是一个示例:

package com.codeke.java.test;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class Test {
    public static void main(String[] args) {
        // 实例化几个BigDecimal对象
        BigDecimal num1 = new BigDecimal("123456.123456");
        BigDecimal num2 = new BigDecimal("789.456");

        // 测试BigDecimal的常用方法
        System.out.println("num1.abs() = " + num1.abs());
        System.out.println("num1.add(num2) = " + num1.add(num2));
        System.out.println("num1.subtract(num2) = " + num1.subtract(num2));
        System.out.println("num1.multiply(num2) = " + num1.multiply(num2));
        System.out.println("num1.divide(num2, BigDecimal.ROUND_HALF_EVEN) = " + num1.divide(num2, BigDecimal.ROUND_HALF_EVEN));
        System.out.println("num1.divide(num2, 2, RoundingMode.HALF_EVEN) = " + num1.divide(num2, 2, RoundingMode.HALF_EVEN));
        System.out.println("num2.pow(2) = " + num2.pow(2));
        System.out.println("num2.round(new MathContext(3, RoundingMode.HALF_EVEN)) = " + num2.round(new MathContext(3, RoundingMode.HALF_EVEN)));
        System.out.println("num1.max(num2) = " + num1.max(num2));
        System.out.println("num1.min(num2) = " + num1.min(num2));
        System.out.println("num1.longValue() = " + num1.longValue());
        System.out.println("num2.intValue() = " + num2.intValue());
        System.out.println("num1.doubleValue() = " + num1.doubleValue());
        System.out.println("num2.floatValue() = " + num2.floatValue());
        try {
            System.out.println("num1.multiply(num2).byteValueExact() = " + num1.multiply(num2).byteValueExact());
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }
}

执行输出结果:

num1.abs() = 123456.123456
num1.add(num2) = 124245.579456
num1.subtract(num2) = 122666.667456
num1.multiply(num2) = 97463177.399079936
num1.divide(num2, BigDecimal.ROUND_HALF_EVEN) = 156.381259
num1.divide(num2, 2, RoundingMode.HALF_EVEN) = 156.38
num2.pow(2) = 623240.775936
num2.round(new MathContext(3, RoundingMode.HALF_EVEN)) = 789
num1.max(num2) = 123456.123456
num1.min(num2) = 789.456
num1.longValue() = 123456
num2.intValue() = 789
num1.doubleValue() = 123456.123456
num2.floatValue() = 789.456
java.lang.ArithmeticException: Rounding necessary
	at java.math.BigDecimal.commonNeedIncrement(BigDecimal.java:4179)
	at java.math.BigDecimal.needIncrement(BigDecimal.java:4235)
	at java.math.BigDecimal.divideAndRound(BigDecimal.java:4143)
	at java.math.BigDecimal.setScale(BigDecimal.java:2455)
	at java.math.BigDecimal.longValueExact(BigDecimal.java:3121)
	at java.math.BigDecimal.byteValueExact(BigDecimal.java:3218)
	at com.codeke.java.test1.Test.main(Test.java:29)

说明:

  • 本例演示了java.math.BigDecimal类中的常用方法,如abs()add(BigDecimal augend)subtract(BigDecimal subtrahend)multiply(BigDecimal multiplicand)divide(BigDecimal divisor, int roundingMode)divide(BigDecimal divisor, int scale, RoundingMode roundingMode)pow(int n)round(MathContext mc)max(BigDecimal val)min(BigDecimal val)longValue()intValue()doubleValue()floatValue()byteValueExact()等。
  • 注意,在部分方法中,如divide(BigDecimal divisor, int roundingMode)舍入模式可以使用java.math.BigDecimal中的常量来指定。
  • 浮点数的除法,经常会出现除不尽的情况,故尽量要通过参数指定精确小数位数舍入模式
  • java.math.BigDecimal类中继承自java.lang.Number方法(intValue()longValue()等),也出现java.math.BigDecimal对象表示的数字超过基本数据类型可以表示范围的情况,此时,转换时会丢失高位信息,转换结果不一定准确。如果需要准确地转换成基本类型==,可以使用java.math.BigDecimal类提供的byteValueExact()shortValueExact()intValueExact()longValueExact()方法

你可能感兴趣的:(JAVA学习笔记)