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

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

創(chuàng)建對(duì)象
Integer i1 = 21;
Integer i2 = Integer.valueOf("21");
自動(dòng)拆裝箱
所謂「拆箱」就是指,包裝類型轉(zhuǎn)換為基本類型的過程,而所謂的「裝箱」則是基本類型到包裝類型的過程。
Integer integer = new Integer(21);//裝箱 int num = integer.intValue();//拆箱
自從 jdk1.5 以后,引入了自動(dòng)拆裝箱的概念,上述代碼可以簡(jiǎn)化成如下代碼:
Integer integer = 21;//裝箱 int num = integer;//拆箱
我們來進(jìn)行分析一下。
自動(dòng)裝箱
Integer integer = 21; 給一個(gè) Integer 類型的對(duì)象不能直接賦一個(gè)基本類型值,integer 保存的是一個(gè)內(nèi)存地址。21 自動(dòng)封裝成一個(gè)對(duì)象,把這個(gè)對(duì)象的地址賦值給 integer。這個(gè)對(duì)象是自動(dòng)創(chuàng)建的,是自動(dòng)裝箱。在程序中編譯成:Integer integer = Integer.valueOf(21);
自動(dòng)拆箱
int num = integer; 定義一個(gè) int 類型變量,num 應(yīng)該直接存一個(gè)值,integer 保存的是一個(gè)內(nèi)存地址。integer 自動(dòng)取出對(duì)象中的值,然后把值賦值給 num。系統(tǒng)為我們執(zhí)行了:int num = integer.intValue();
拆裝箱是需要方法調(diào)用的,耗資源,所以我們的程序中應(yīng)當(dāng)盡量避免大量的「拆裝箱」操作。
自動(dòng)拆箱要當(dāng)心 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);
}
}
運(yùn)行時(shí)會(huì)報(bào)空指針

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

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

那為什么會(huì)出現(xiàn)這種情況呢?
因?yàn)椴徽撌?float 還是 double 都是浮點(diǎn)數(shù),而計(jì)算機(jī)是二進(jìn)制的,浮點(diǎn)數(shù)會(huì)失去一定的精確度。究其根本原因是,十進(jìn)制值通常沒有完全相同的二進(jìn)制表示形式,十進(jìn)制數(shù)的二進(jìn)制表示形式可能不精確。只能無限接近于那個(gè)值。
BigDecimal 的作用就是做精確的浮點(diǎn)運(yùn)算
構(gòu)造方法
public BigDecimal(double val) 將double表示形式轉(zhuǎn)換為BigDecimal *不建議使用 public BigDecimal(int val) 將int表示形式轉(zhuǎn)換成BigDecimal public BigDecimal(String val) 將String表示形式轉(zhuǎn)換成BigDecimal * 推薦使用
參數(shù)類型為 double 的構(gòu)造方法的結(jié)果有一定的不可預(yù)知性。所以通常情況下不使用。
String 構(gòu)造方法是完全可預(yù)知的:寫入 newBigDecimal(“0.1”), 將創(chuàng)建一個(gè) BigDecimal,它正好等于預(yù)期的 0.1。因此,比較而言,通常建議優(yōu)先使用 String 構(gòu)造方法。
當(dāng) double 必須用作 BigDecimal 的源時(shí),請(qǐng)使用 Double.toString(double) 轉(zhuǎn)成String,再使用 String 構(gòu)造方法?;蚴褂?BigDecimal 的靜態(tài)方法 valueOf。
舉例:使用 double 做構(gòu)造參數(shù)的正確使用
如下程序中 bd1 展示了 參數(shù)類型為 double 的構(gòu)造方法的的不可預(yù)知性,db2 展示了 String 的構(gòu)造方法,bd3、bd4 展示了正確使用 double 做為參數(shù)的構(gòu)造方法。
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);
運(yùn)行結(jié)果:

方法
add(BigDecimal bd)+保留位數(shù),舍入方式)
subtract(BigDecimal bd)-
multiply(BigDecimal bd)*
divide(BigDecimal bd)/
divide(BigDecimal bd,
setScale(保留位數(shù),舍入方式) 舍入運(yùn)算,運(yùn)算結(jié)果會(huì)封裝成新的大數(shù)字對(duì)象返回
舉例:實(shí)現(xiàn)本節(jié)開頭的精確運(yùn)算
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));
運(yùn)行結(jié)果:

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

舉例:計(jì)算降落距離
System.out.println("輸入降落時(shí)間");
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 + "米");
運(yùn)行結(jié)果:

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

方法
BigInteger abs() 返回大整數(shù)的絕對(duì)值
BigInteger add(BigInteger val) 返回兩個(gè)大整數(shù)的和
BigInteger and(BigInteger val) 返回兩個(gè)大整數(shù)的按位與的結(jié)果
BigInteger andNot(BigInteger val) 返回兩個(gè)大整數(shù)與非的結(jié)果
BigInteger divide(BigInteger val) 返回兩個(gè)大整數(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) 返回兩個(gè)大整數(shù)的最大者
BigInteger min(BigInteger val) 返回兩個(gè)大整數(shù)的最小者
BigInteger mod(BigInteger val) 用當(dāng)前大整數(shù)對(duì)val求模
BigInteger multiply(BigInteger val) 返回兩個(gè)大整數(shù)的積
BigInteger negate() 返回當(dāng)前大整數(shù)的相反數(shù)
BigInteger not() 返回當(dāng)前大整數(shù)的非
BigInteger or(BigInteger val) 返回兩個(gè)大整數(shù)的按位或
BigInteger pow(int exponent) 返回當(dāng)前大整數(shù)的exponent次方
BigInteger remainder(BigInteger val) 返回當(dāng)前大整數(shù)除以val的余數(shù)
BigInteger leftShift(int n) 將當(dāng)前大整數(shù)左移n位后返回
BigInteger rightShift(int n) 將當(dāng)前大整數(shù)右移n位后返回
BigInteger subtract(BigInteger val)返回兩個(gè)大整數(shù)相減的結(jié)果
byte[] toByteArray(BigInteger val)將大整數(shù)轉(zhuǎn)換成二進(jìn)制反碼保存在byte數(shù)組中
String toString() 將當(dāng)前大整數(shù)轉(zhuǎn)換成十進(jìn)制的字符串形式
BigInteger xor(BigInteger val) 返回兩個(gè)大整數(shù)的異或
到此這篇關(guān)于JAVA基本類型包裝類 BigDecimal BigInteger 的使用的文章就介紹到這了,更多相關(guān)JAVA BigDecimal、BigInteger 的使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ IDEA 2020.2 配置大全詳細(xì)圖文教程(更新中)
這篇文章主要介紹了IntelliJ IDEA 2020.2 配置大全(更新中),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
java調(diào)用shell腳本及注意事項(xiàng)說明
這篇文章主要介紹了java調(diào)用shell腳本及注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Java 服務(wù)端消息推送的實(shí)現(xiàn)小結(jié)
本文主要介紹了Java 服務(wù)端消息推送的實(shí)現(xiàn)小結(jié),主要包括四種常見的消息實(shí)時(shí)推送方案:短輪詢、長(zhǎng)輪詢、SSE?和?WebSocket,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
Java語言實(shí)現(xiàn)反轉(zhuǎn)鏈表代碼示例
這篇文章主要介紹了Java語言實(shí)現(xiàn)反轉(zhuǎn)鏈表代碼示例,小編覺得挺不錯(cuò)的,這里分享給大家,供需要的朋友參考。2017-10-10
學(xué)會(huì)Pulsar Consumer的使用方式
這篇文章主要介紹了Pulsar Consumer的使用方式,全文使用大量的代碼來做了詳細(xì)的講解,感興趣的小伙伴可以參考一下這篇文章,希望讀完能對(duì)你有很大的幫助2021-08-08
Jenkins集成sonarQube實(shí)現(xiàn)代碼質(zhì)量檢查過程圖解
這篇文章主要介紹了Jenkins集成sonarQube實(shí)現(xiàn)代碼質(zhì)量檢查過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09

