JAVA基本類型包裝類 BigDecimal BigInteger 的使用
1、了解包裝類
Java
中預定義了八種基本數據類型,包括:byte
,int
,long
,double
,float
,boolean
,char
,short
?;绢愋团c對象類型最大的不同點在于,基本類型基于數值,對象類型基于引用。
例如有一個方法 f() ,它的參數分別是對象類型 和 基本類型:
void f(Object obj){ //參數引用類型,保存的是內存地址 } f(123){ //基本類型 }
基本類型基于數值,所以基本類型是沒有類而言的,是不存在類的概念的,也就是說,變量只能存儲數值,而不具備操作數據的方法。
對象類型則截然不同,變量實際上是某個類的實例,可以擁有屬性方法等信息,不再單一的存儲數值,可以提供各種各樣對數值的操作方法,但代價就是犧牲一些性能并占用更多的內存空間。
Java
中提供了哪些「包裝類型」來彌補「基本類型」不具備面向對象思想的劣勢呢?看下圖:
java.lang.Number
這里需要提到 java.lang.Number
,它是所有數值類的父類,其直接子類包括:Byte
、Short
、Integer
、Long
、Float
、Double
、BigDecimal
、BigInteger
。
這些類取出內部封裝的基本類型值的方法很簡單也很好記:byteValue()
、shortValue()
、intValue()
、longValue()
、floatValue()
、doubleValue()
其他使用方法也基本相同,下面我們以 Integer 和 Double 為例具體講一講
2、Integer
首先需要明確一點的是,既然 Integer
是 int
的包裝類型,那么必然 Integer 也能像 int 一樣存儲整型數值。有興趣的同學可以看看源碼。
Integer
類的內部定義了一個私有字段 value
,專門用于保存一個整型數值,整個包裝類就是圍繞著這個 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
實例緩存數組,范圍:-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 類型的數值,按十進制解析成 255
Integer.parseInt("11111111", 2)
//按二進制解析成 255
Integer.parseInt("377",8);
//按八進制解析成 255
Integer.parseInt("ff", 16);
//按十六進制解析成 255
3、進制轉換
Integer.toBinaryString(255);
//將數字轉成二進制,解析成"11111111"
Integer.toOctalString(255);
//將數字轉換成八進制,解析成"377"
Integer.toHexString(255);
//將數字轉換成十六進制,解析成"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、將數字字符串轉換為 Double 數值 Double.parseDouble("3.14");
3、判斷浮點數特殊值
Double.isInfinite(double d):
如果此對象表示的值是正無窮大或負無窮大,則返回 true;否則返回
Double.isNaN(double d):
如果此 Double 值是一個非數字值,則返回 true,否則返回 false
Infinity:無窮大 NaN:not a number
4、BigDecimal
浮點數的運算是不精確的,我們看以下運算
System.out.println(2 - 1.9); System.out.println(4.35 * 100);
運算結果:
那為什么會出現這種情況呢?
因為不論是 float
還是 double
都是浮點數,而計算機是二進制的,浮點數會失去一定的精確度。究其根本原因是,十進制值通常沒有完全相同的二進制表示形式,十進制數的二進制表示形式可能不精確。只能無限接近于那個值。
BigDecimal
的作用就是做精確的浮點運算
構造方法
public BigDecimal(double val) 將double表示形式轉換為BigDecimal *不建議使用 public BigDecimal(int val) 將int表示形式轉換成BigDecimal public BigDecimal(String val) 將String表示形式轉換成BigDecimal * 推薦使用
參數類型為 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 做構造參數的正確使用
如下程序中 bd1 展示了 參數類型為 double
的構造方法的的不可預知性,db2 展示了 String
的構造方法,bd3、bd4 展示了正確使用 double
做為參數的構造方法。
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)+
保留位數,舍入方式)
subtract(BigDecimal bd)-
multiply(BigDecimal bd)*
divide(BigDecimal bd)/
divide(BigDecimal bd,
setScale(保留位數,舍入方式)
舍入運算,運算結果會封裝成新的大數字對象返回
舉例:實現本節(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
作用:做超大整數運算
在 Java中,由CPU原生提供的整型最大范圍是 64 位 long 型整數。使用 long 型整數可以直接通過 CPU 指令進行計算,速度非???。
如果我們使用的整數范圍超過了 long 型怎么辦?這個時候,就只能用軟件來模擬一個大整數。java.math.BigInteger
就是用來表示任意大小的整數。
我們通過一個例子就可以了解它的使用。
舉例:計算階乘
public class Main { public static void main(String[] args) { System.out.println("輸入數字來計算階乘:"); int number = new Scanner(System.in).nextInt(); System.out.println("階乘結果:" + f(number)); } private static String f(int number) { //超大整數運算 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()
返回大整數的絕對值
BigInteger add(BigInteger val)
返回兩個大整數的和
BigInteger and(BigInteger val)
返回兩個大整數的按位與的結果
BigInteger andNot(BigInteger val)
返回兩個大整數與非的結果
BigInteger divide(BigInteger val)
返回兩個大整數的商
double doubleValue()
返回大整數的double類型的值
float floatValue()
返回大整數的float類型的值
BigInteger gcd(BigInteger val)
返回大整數的最大公約數
int intValue()
返回大整數的整型值
long longValue()
返回大整數的long型值
BigInteger max(BigInteger val)
返回兩個大整數的最大者
BigInteger min(BigInteger val)
返回兩個大整數的最小者
BigInteger mod(BigInteger val)
用當前大整數對val求模
BigInteger multiply(BigInteger val)
返回兩個大整數的積
BigInteger negate()
返回當前大整數的相反數
BigInteger not()
返回當前大整數的非
BigInteger or(BigInteger val)
返回兩個大整數的按位或
BigInteger pow(int exponent)
返回當前大整數的exponent次方
BigInteger remainder(BigInteger val)
返回當前大整數除以val的余數
BigInteger leftShift(int n)
將當前大整數左移n位后返回
BigInteger rightShift(int n)
將當前大整數右移n位后返回
BigInteger subtract(BigInteger val)
返回兩個大整數相減的結果
byte[] toByteArray(BigInteger val)
將大整數轉換成二進制反碼保存在byte數組中
String toString()
將當前大整數轉換成十進制的字符串形式
BigInteger xor(BigInteger val)
返回兩個大整數的異或
到此這篇關于JAVA基本類型包裝類 BigDecimal BigInteger
的使用的文章就介紹到這了,更多相關JAVA BigDecimal、BigInteger 的使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IntelliJ IDEA 2020.2 配置大全詳細圖文教程(更新中)
這篇文章主要介紹了IntelliJ IDEA 2020.2 配置大全(更新中),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08Jenkins集成sonarQube實現代碼質量檢查過程圖解
這篇文章主要介紹了Jenkins集成sonarQube實現代碼質量檢查過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09