本文是Java基础课程的第十二课。本文主要介绍Java中包装类的概念及使用,Java针对数字处理所提供的一些常用的类库,如java.text.NumberFormat、java.lang.Math、java.math.BigInteger等等
关于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.Character
类和java.lang.Integer
类外,其他六个类的类名和其所对应的基本数据类型一致,只是类名的第一个字母大写了。
在这些包装类中,表示数字的包装类都继承了java.lang.Number
类,如图:
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
说明:
integer1
和integer2
都是通过java.lang.Integer
类的静态方法valueOf(int i)
获得的,包装的数字都是100
,使用==
操作符比较变量integer1
和integer2
,得到的结果是true
;变量integer3
和integer4
同样都是通过java.lang.Integer
类的静态方法valueOf(int i)
获得的,只不过包装的数字都是128
,使用==
操作符比较它们时,得到的结果却是false
。本质上,变量integer1
和integer2
引用了同一块内存地址编号,而变量integer3
和integer4
则分别引用了不同的内存地址编号。产生这种现象的原因是,java.lang.Integer
类中包含一个静态成员内部类IntegerCache
,该类中有一个java.lang.Integer
类型的数组cache
,该数组中保存着一系列的java.lang.Integer
类对象,依次包装了从-128
到127
(默认)这一范围内的数字,作为缓存。当使用valueOf(int i)
获取java.lang.Integer
类对象时,会先判断前述的缓存中是否有对应的对象,有则直接返回,没有则实例化一个新的java.lang.Integer
类对象返回。包装类java.lang.Character
、java.lang.Byte
、java.lang.Short
、java.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
说明:
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()
方法,先将字符串转换为基本数据类型的值,然后再实例化包装类的对象。其三、作为和基本数据类型对应的引用类型存在,方便涉及到对象的操作。这一方面的作用在后续的章节中将会看到。
装箱的含义是,将基本数据类型封装为包装类对象;拆箱的含义是,将包装类中包装的基本数据类型数据取出。自动装箱和自动拆箱即装箱和拆箱的过程都是自发完成的。
自动装箱和自动拆箱是一种编译器的机制,自动装箱本质上是在编译过程中,在需要装箱的地方调用各包装类对应的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中提供了丰富的类库,帮助开发人员进行数学运算、数字格式化等与数字处理有关的操作。
在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
类中均已经被声明为常量。开发人员在使用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 |
科学记数法 |
% |
用百分数表示数字 |
java.lang
包下,JDK提供了Math
类。该类中提供了大量和基本数学运算相关的方法和常量,方法如加减乘除、指数、对数、平方根、三角函数等,常量最主要的两个是Math.E
和Math.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)
方法,请注意比较它们的区别。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 |
返回值为 this 的exponent 次幂的BigInteger 实例 |
max(BigInteger val) |
BigInteger |
返回this 和val 中值较大的一个 |
min(BigInteger val) |
BigInteger |
返回this 和val 中值较小的一个 |
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
异常。先来看下面的示例:
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
说明:
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 |
返回值为 this 的n 次幂的BigDecimal 实例 |
pow(int n, MathContext mc) |
BigDecimal |
返回值为 this 的n 次幂的BigDecimal 实例,并根据上下文进行舍入 |
round(MathContext mc) |
BigDecimal |
将BigDecimal 实例按指定的上下文进行舍入 |
max(BigDecimal val) |
BigDecimal |
返回this 和val 中值较大的一个 |
min(BigDecimal val) |
BigDecimal |
返回this 和val 中值较小的一个 |
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()
方法。