JAVA基本類型包裝類 BigDecimal BigInteger 的使用
1、了解包裝類
Java 中預定義了八種基本數(shù)據(jù)類型,包括:byte,int,long,double,float,boolean,char,short?;绢愋团c對象類型最大的不同點在于,基本類型基于數(shù)值,對象類型基于引用。
例如有一個方法 f() ,它的參數(shù)分別是對象類型 和 基本類型:
void f(Object obj){
//參數(shù)引用類型,保存的是內存地址
}
f(123){
//基本類型
}
基本類型基于數(shù)值,所以基本類型是沒有類而言的,是不存在類的概念的,也就是說,變量只能存儲數(shù)值,而不具備操作數(shù)據(jù)的方法。
對象類型則截然不同,變量實際上是某個類的實例,可以擁有屬性方法等信息,不再單一的存儲數(shù)值,可以提供各種各樣對數(shù)值的操作方法,但代價就是犧牲一些性能并占用更多的內存空間。
Java 中提供了哪些「包裝類型」來彌補「基本類型」不具備面向對象思想的劣勢呢?看下圖:

java.lang.Number
這里需要提到 java.lang.Number,它是所有數(shù)值類的父類,其直接子類包括:Byte、Short、Integer、Long、Float、Double、BigDecimal、BigInteger。
這些類取出內部封裝的基本類型值的方法很簡單也很好記:byteValue() 、shortValue() 、intValue() 、longValue() 、floatValue() 、doubleValue()
其他使用方法也基本相同,下面我們以 Integer 和 Double 為例具體講一講
2、Integer
首先需要明確一點的是,既然 Integer 是 int 的包裝類型,那么必然 Integer 也能像 int 一樣存儲整型數(shù)值。有興趣的同學可以看看源碼。
Integer 類的內部定義了一個私有字段 value,專門用于保存一個整型數(shù)值,整個包裝類就是圍繞著這個 value 封裝了各種不同操作的方法:

創(chuàng)建對象
Integer i1 = 21;
Integer i2 = Integer.valueOf("21");
自動拆裝箱
所謂「拆箱」就是指,包裝類型轉換為基本類型的過程,而所謂的「裝箱」則是基本類型到包裝類型的過程。
Integer integer = new Integer(21);//裝箱 int num = integer.intValue();//拆箱
自從 jdk1.5 以后,引入了自動拆裝箱的概念,上述代碼可以簡化成如下代碼:
Integer integer = 21;//裝箱 int num = integer;//拆箱
我們來進行分析一下。
自動裝箱
Integer integer = 21; 給一個 Integer 類型的對象不能直接賦一個基本類型值,integer 保存的是一個內存地址。21 自動封裝成一個對象,把這個對象的地址賦值給 integer。這個對象是自動創(chuàng)建的,是自動裝箱。在程序中編譯成:Integer integer = Integer.valueOf(21);
自動拆箱
int num = integer; 定義一個 int 類型變量,num 應該直接存一個值,integer 保存的是一個內存地址。integer 自動取出對象中的值,然后把值賦值給 num。系統(tǒng)為我們執(zhí)行了:int num = integer.intValue();
拆裝箱是需要方法調用的,耗資源,所以我們的程序中應當盡量避免大量的「拆裝箱」操作。
自動拆箱要當心 null 值
我們看以下程序:
public class Main {
public static void main(String[] args) {
int j = 0;
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(null);
for (int i : list) {
j += i;
}
System.out.println(j);
}
}
運行時會報空指針

所以在獲取到值有可能為空要裝箱的時候,一定要加上 null 值的校驗。所以可以把程序改為:

程序結果為:
3
面試題1
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2);
System.out.println(i3==i4);
輸出結果:
true
false
Integer 類中,存在 Integer 實例緩存數(shù)組,范圍:-128 - 127。如果在自動裝箱的時候給局部變量的int型值是在上面的范圍之中,如果是范圍內的值,就使用存在的緩存對象;如果不是范圍內的值,會新建對象。
面試題2
Integer i1 = new Integer(21);
Integer i2 = new Integer(21);
System.out.println(i1 == i2);
System.out.println(i1.equals(i2));
輸出結果:
false
true
如果new就會在堆內存開辟空間,new兩次就開辟兩段空間,兩段空間地址值一定不一樣。不推薦這么寫,過時了。
方法
1、從 Number 繼承的 6 個方法
byteValue() 、shortValue() 、intValue() 、longValue() 、floatValue() 、doubleValue()
2、字符串解析成 int
Integer.parseInt("255"); //將字符串轉換為 int 類型的數(shù)值,按十進制解析成 255
Integer.parseInt("11111111", 2) //按二進制解析成 255
Integer.parseInt("377",8); //按八進制解析成 255
Integer.parseInt("ff", 16); //按十六進制解析成 255
3、進制轉換
Integer.toBinaryString(255); //將數(shù)字轉成二進制,解析成"11111111"
Integer.toOctalString(255); //將數(shù)字轉換成八進制,解析成"377"
Integer.toHexString(255); //將數(shù)字轉換成十六進制,解析成"ff"
完整程序
System.out.println("i1:" + Integer.parseInt("255"));
System.out.println("i2:" + Integer.parseInt("11111111", 2));
System.out.println("i3:" + Integer.parseInt("377", 8));
System.out.println("i4:" + Integer.parseInt("ff", 16));
System.out.println("s1:" + Integer.toBinaryString(255));
System.out.println("s2:" + Integer.toOctalString(255));
System.out.println("s3:" + Integer.toHexString(255));
輸出結果
255
255
255
255
11111111
377
ff
3、Double
Double 類在對象中包裝了一個基本類型 double 的值。Double 類對象包含一個 double 類型的字段。此外,該類還提供了多個方法,可以將 double 類型與 String 類型相互轉換,同時 還提供了處理 double 類型時比較常用的常量和方法。
創(chuàng)建對象
Double d1 = 21d;
Double d2 = Double.valueOf("21");
方法
1、從Number類繼承的6個方法,同上
2、將數(shù)字字符串轉換為 Double 數(shù)值 Double.parseDouble("3.14");3、判斷浮點數(shù)特殊值
Double.isInfinite(double d):如果此對象表示的值是正無窮大或負無窮大,則返回 true;否則返回
Double.isNaN(double d):如果此 Double 值是一個非數(shù)字值,則返回 true,否則返回 false
Infinity:無窮大 NaN:not a number
4、BigDecimal
浮點數(shù)的運算是不精確的,我們看以下運算
System.out.println(2 - 1.9); System.out.println(4.35 * 100);
運算結果:

那為什么會出現(xiàn)這種情況呢?
因為不論是 float 還是 double 都是浮點數(shù),而計算機是二進制的,浮點數(shù)會失去一定的精確度。究其根本原因是,十進制值通常沒有完全相同的二進制表示形式,十進制數(shù)的二進制表示形式可能不精確。只能無限接近于那個值。
BigDecimal 的作用就是做精確的浮點運算
構造方法
public BigDecimal(double val) 將double表示形式轉換為BigDecimal *不建議使用 public BigDecimal(int val) 將int表示形式轉換成BigDecimal public BigDecimal(String val) 將String表示形式轉換成BigDecimal * 推薦使用
參數(shù)類型為 double 的構造方法的結果有一定的不可預知性。所以通常情況下不使用。
String 構造方法是完全可預知的:寫入 newBigDecimal(“0.1”), 將創(chuàng)建一個 BigDecimal,它正好等于預期的 0.1。因此,比較而言,通常建議優(yōu)先使用 String 構造方法。
當 double 必須用作 BigDecimal 的源時,請使用 Double.toString(double) 轉成String,再使用 String 構造方法。或使用 BigDecimal 的靜態(tài)方法 valueOf。
舉例:使用 double 做構造參數(shù)的正確使用
如下程序中 bd1 展示了 參數(shù)類型為 double 的構造方法的的不可預知性,db2 展示了 String 的構造方法,bd3、bd4 展示了正確使用 double 做為參數(shù)的構造方法。
BigDecimal bd1 = new BigDecimal(1.9);
BigDecimal bd2 = new BigDecimal("1.9");
BigDecimal bd3 = BigDecimal.valueOf(1.9);
BigDecimal bd4 = new BigDecimal(Double.toString(1.9));
System.out.println("db1:" + bd1);
System.out.println("db2:" + bd2);
System.out.println("db3:" + bd3);
System.out.println("db4:" + bd4);
運行結果:

方法
add(BigDecimal bd)+保留位數(shù),舍入方式)
subtract(BigDecimal bd)-
multiply(BigDecimal bd)*
divide(BigDecimal bd)/
divide(BigDecimal bd,
setScale(保留位數(shù),舍入方式) 舍入運算,運算結果會封裝成新的大數(shù)字對象返回
舉例:實現(xiàn)本節(jié)開頭的精確運算
BigDecimal bd1 = new BigDecimal("2");
BigDecimal bd2 = new BigDecimal("1.9");
System.out.println("2 - 1.9 = " + bd1.subtract(bd2));
BigDecimal bd3 = new BigDecimal("4.35");
BigDecimal bd4 = new BigDecimal("100");
System.out.println("4.35 * 100 = " + bd3.multiply(bd4));
運行結果:

舉例:四舍五入
BigDecimal bd = BigDecimal.valueOf(2.345);
double result = bd.setScale(2, RoundingMode.HALF_UP).doubleValue();
System.out.println("result:" + result);
運行結果:

舉例:計算降落距離
System.out.println("輸入降落時間");
double t = new Scanner(System.in).nextDouble();
//1/2*9.8*t*t
BigDecimal a = BigDecimal.valueOf(0.5);
BigDecimal b = BigDecimal.valueOf(9.8);
BigDecimal c = BigDecimal.valueOf(t);
double result = a.multiply(b).multiply(c.pow(2)).doubleValue();
System.out.println("降落距離:" + result + "米");
運行結果:

5、BigInteger
作用:做超大整數(shù)運算
在 Java中,由CPU原生提供的整型最大范圍是 64 位 long 型整數(shù)。使用 long 型整數(shù)可以直接通過 CPU 指令進行計算,速度非??臁?/p>
如果我們使用的整數(shù)范圍超過了 long 型怎么辦?這個時候,就只能用軟件來模擬一個大整數(shù)。java.math.BigInteger 就是用來表示任意大小的整數(shù)。
我們通過一個例子就可以了解它的使用。
舉例:計算階乘
public class Main {
public static void main(String[] args) {
System.out.println("輸入數(shù)字來計算階乘:");
int number = new Scanner(System.in).nextInt();
System.out.println("階乘結果:" + f(number));
}
private static String f(int number) {
//超大整數(shù)運算
BigInteger bd = BigInteger.valueOf(number);
for (int i = number - 1; i >= 1; i--) {
BigInteger bi = BigInteger.valueOf(i);
bd = bd.multiply(bi);
}
return bd.toString();
}
}
運行結果:

方法
BigInteger abs() 返回大整數(shù)的絕對值
BigInteger add(BigInteger val) 返回兩個大整數(shù)的和
BigInteger and(BigInteger val) 返回兩個大整數(shù)的按位與的結果
BigInteger andNot(BigInteger val) 返回兩個大整數(shù)與非的結果
BigInteger divide(BigInteger val) 返回兩個大整數(shù)的商
double doubleValue() 返回大整數(shù)的double類型的值
float floatValue() 返回大整數(shù)的float類型的值
BigInteger gcd(BigInteger val) 返回大整數(shù)的最大公約數(shù)
int intValue() 返回大整數(shù)的整型值
long longValue() 返回大整數(shù)的long型值
BigInteger max(BigInteger val) 返回兩個大整數(shù)的最大者
BigInteger min(BigInteger val) 返回兩個大整數(shù)的最小者
BigInteger mod(BigInteger val) 用當前大整數(shù)對val求模
BigInteger multiply(BigInteger val) 返回兩個大整數(shù)的積
BigInteger negate() 返回當前大整數(shù)的相反數(shù)
BigInteger not() 返回當前大整數(shù)的非
BigInteger or(BigInteger val) 返回兩個大整數(shù)的按位或
BigInteger pow(int exponent) 返回當前大整數(shù)的exponent次方
BigInteger remainder(BigInteger val) 返回當前大整數(shù)除以val的余數(shù)
BigInteger leftShift(int n) 將當前大整數(shù)左移n位后返回
BigInteger rightShift(int n) 將當前大整數(shù)右移n位后返回
BigInteger subtract(BigInteger val)返回兩個大整數(shù)相減的結果
byte[] toByteArray(BigInteger val)將大整數(shù)轉換成二進制反碼保存在byte數(shù)組中
String toString() 將當前大整數(shù)轉換成十進制的字符串形式
BigInteger xor(BigInteger val) 返回兩個大整數(shù)的異或
到此這篇關于JAVA基本類型包裝類 BigDecimal BigInteger 的使用的文章就介紹到這了,更多相關JAVA BigDecimal、BigInteger 的使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IntelliJ IDEA 2020.2 配置大全詳細圖文教程(更新中)
這篇文章主要介紹了IntelliJ IDEA 2020.2 配置大全(更新中),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08
Jenkins集成sonarQube實現(xiàn)代碼質量檢查過程圖解
這篇文章主要介紹了Jenkins集成sonarQube實現(xiàn)代碼質量檢查過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09

