整型:byte(最小的資料型別)、short(短整型)、int(整型)、long(長整型);
浮點型:float(浮點型)、double(雙精度浮點型);
字元型:char(字元型);
布林型:boolean(布林型)。
資料型別名稱 | 佔用位元組 | 預設值 | 最小值最大值 | 對應包裝類 | |
---|---|---|---|---|---|
整數型別 | byte | 1 | 0 | -128(-2^7)~ 127(2^7-1) | Byte |
整數型別 | short | 2 | 0 | -32768(-2^15)~ 32767(2^15 - 1) | Short |
整數型別 | int | 4 | 0 | -2,147,483,648(-2^31)~ 2,147,483,647(2^31 - 1) | Integer |
整數型別 | long | 8 | 0.0L | -9,223,372,036,854,775,808(-2^63)~ 9,223,372,036,854,775,807(2^63 -1) | Long |
浮點型別 | float | 4 | 0.0f | 1.4E-45 ~ 3.4028235E38 | Float |
浮點型別 | double | 8 | 0.0 | 4.9E-324 ~ 1.7976931348623157E308 | Double |
字元型別 | char | 2 | 空 | \u0000(即為0)~ \uffff(即為65,535) | Character |
布林型別 | boolean | 1 | flase | true 和 false | Boolean |
Integer 快取是 Java 5 中引入的一個有助於節省記憶體、提高效能的特性。
Integer的快取機制: Integer是對小資料(-128127)是有快取的,再jvm初始化的時候,資料-128127之間的數字便被快取到了本地記憶體中,如果初始化-128~127之間的數字,會直接從記憶體中取出,不需要新建一個物件.
首先看一個使用 Integer 的示例程式碼,展示了 Integer 的快取行為。
/**
* 測試Integer的快取 IntegerCache.cache
*/
private static void testIntegerCache() {
System.out.println("---int---");
int a = 127, b = 127;
System.out.println(a == b); //true
a = 128;
b = 128;
System.out.println(a == b); //true
System.out.println("---Integer---");
Integer aa = 127, bb = 127;
System.out.println(aa == bb); //true
aa = 128;
bb = 128;
System.out.println(aa == bb); //false
System.out.println(aa.equals(bb)); //true
}
在 Java 5 中,為 Integer 的操作引入了一個新的特性,用來節省記憶體和提高效能。整型物件在內部實現中透過使用相同的物件引用實現了快取和重用。
上面的規則適用於整數區間 -128 到 +127。
Java 編譯器把原始型別自動轉換為封裝類的過程稱為自動裝箱(autoboxing),這相當於呼叫 valueOf 方法。
下面是 JDK 1.8.0 build 25 中的程式碼。
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在建立新的 Integer 物件之前會先在 IntegerCache.cache (是個Integer型別的陣列)中查詢。
IntegerCache 是 Integer 類中一個私有的靜態類,負責 Integer 的快取。
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
Javadoc 詳細的說明這個類是用來實現快取支援,並支援 -128 到 127 之間的自動裝箱過程。最大值 127 可以透過 JVM 的啟動引數 -XX:AutoBoxCacheMax=size 修改。 快取透過一個 for 迴圈實現。從小到大的建立儘可能多的整數並儲存在一個名為 cache 的整數陣列中。這個快取會在 Integer 類第一次被使用的時候被初始化出來。以後,就可以使用快取中包含的例項物件,而不是建立一個新的例項(在自動裝箱的情況下)。
實際上在 Java 5 中引入這個特性的時候,範圍是固定的 -128 至 +127。後來在 Java 6 中,最大值對映到 java.lang.Integer.IntegerCache.high,可以使用 JVM 的啟動引數設定最大值。這使我們可以根據應用程式的實際情況靈活地調整來提高效能。是什麼原因選擇這個 -128 到 127 這個範圍呢?因為這個範圍的整數值是使用最廣泛的。 在程式中第一次使用 Integer 的時候也需要一定的額外時間來初始化這個快取。
Java 語言規範中的快取行為
在 Boxing Conversion 部分的Java語言規範(JLS)規定如下:
如果一個變數 p 的值屬於:-128至127之間的整數(§3.10.1),true 和 false的布林值 (§3.10.3),’u0000′ 至 ‘u007f’ 之間的字元(§3.10.4)中時,將 p 包裝成 a 和 b 兩個物件時,可以直接使用 a == b 判斷 a 和 b 的值是否相等。
其他快取的物件
這種快取行為不僅適用於Integer物件。我們針對所有整數型別的類都有類似的快取機制。
有 ByteCache 用於快取 Byte 物件
有 ShortCache 用於快取 Short 物件
有 LongCache 用於快取 Long 物件
有 CharacterCache 用於快取 Character 物件
Byte,Short,Long 有固定範圍: -128 到 127。對於 Character, 範圍是 0 到 127。除了 Integer 可以透過引數改變範圍外,其它的都不行。
浮點型別是指用於表示小數的資料型別。
單精度和雙精度的區別:
單精度浮點型float,用32位儲存,1位為符號位, 指數8位, 尾數23位,即:float的精度是23位,能精確表達23位的數,超過就被擷取。
雙精度浮點型double,用64位儲存,1位符號位,11位指數,52位尾數,即:double的精度是52位,能精確表達52位的數,超過就被擷取。
雙精度型別double比單精度型別float具有更高的精度,和更大的表示範圍,常常用於科學計算等高精度場合。
浮點數與小數的區別:
1)在賦值或者儲存中浮點型別的精度有限,float是23位,double是52位。
2)在計算機實際處理和運算過程中,浮點數本質上是以二進位制形式存在的。
3)二進位制所能表示的兩個相鄰的浮點值之間存在一定的間隙,浮點值越大,這個間隙也會越大。如果此時對較大的浮點數進行操作時,浮點數的精度問題就會產生,甚至出現一些“不正常”的現象。
為什麼不能用浮點數來表示金額
先給出結論:金額用BigDecimal
1)精度丟失問題
從上面我們可以知道,float的精度是23位,double精度是63位。在儲存或運算過程中,當超出精度時,超出部分會被截掉,由此就會造成誤差。
對於金額而言,捨去不能表示的部分,損失也就產生了。
32位的浮點數由3部分組成:1位元的符號位,8位元的階碼(exponent,指數),23位元的尾數(Mantissa,尾數)。這個結構會表示成一個小數點左邊為1,以底數為2的科學計數法表示的二進位制小數。浮點數的能表示的資料大小範圍由階碼決定,但是能夠表示的精度完全取決於尾數的長度。long的最大值是2的64次方減1,需要63個二進位制位表示,即便是double,52位的尾數也無法完整的表示long的最大值。不能表示的部分也就只能被捨去了。對於金額,捨去不能表示的部分,損失也就產生了。
瞭解了浮點數表示機制後,丟失精度的現象也就不難理解了。但是,這只是浮點數不能表示金額的原因之一。還有一個深刻的原因與進位制轉換有關。十進位制的0.1在二進位制下將是一個無線迴圈小數。
public class MyTest {
public static void main(String[] args) {
float increment = 0.1f;
float expected = 1;
float sum = 0;
for (int i = 0; i < 10; i++) {
sum += increment;
System.out.println(sum);
}
if (expected == sum) {
System.out.println("equal");
} else {
System.out.println("not equal ");
}
}
}
輸出結果:
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001
1.0000001
not equal
2)進位制轉換誤差
從上面我們可以知道,在計算機實際處理和運算過程中,浮點數本質上是以二進位制形式存在的。
而十進位制的0.1在二進位制下將是一個無限迴圈小數,這就會導致誤差的出現。
如果一個小數不是2的負整數次冪,用浮點數表示必然產生浮點誤差。
換言之:A進位制下的有限小數,轉換到B進位制下極有可能是無限小數,誤差也由此產生。
浮點數不精確的根本原因在於:尾數部分的位數是固定的,一旦需要表示的數字的精度高於浮點數的精度,那麼必然產生誤差!
解決這個問題的方法是BigDecimal的類,這個類可以表示任意精度的數字,其原理是:用字串儲存數字,轉換為陣列來模擬大數,實現兩個陣列的數學運算並將結果返回。
BigDecimal的使用要點:
1、BigDecimal變數初始化——必須用傳入String的構造方法
`BigDecimal num1 = ``new` `BigDecimal(0.005);``//用數值轉換成大數,有誤差``BigDecimal num12 = ``new` `BigDecimal(``"0.005"``);``//用字串轉換成大數,無誤差`
因為:不是所有的浮點數都能夠被精確的表示成一個double 型別值,有些浮點數值不能夠被精確的表示成 double 型別值時,它會被表示成與它最接近的 double 型別的值,此時用它來初始化一個大數,會“先造成了誤差,再用產生了誤差的值生成大數”,也就是“將錯就錯”。
2、使用除法函式在divide的時候要設定各種引數,要精確的小數位數和舍入模式,其中有8種舍入模式:
1、ROUND_UP
遠離零的舍入模式。
在丟棄非零部分之前始終增加數字(始終對非零捨棄部分前面的數字加1)。
注意,此舍入模式始終不會減少計算值的大小。
2、ROUND_DOWN
接近零的舍入模式。
在丟棄某部分之前始終不增加數字(從不對捨棄部分前面的數字加1,即截短)。
注意,此舍入模式始終不會增加計算值的大小。
3、ROUND_CEILING
接近正無窮大的舍入模式。
如果 BigDecimal 為正,則舍入行為與 ROUND_UP 相同;
如果為負,則舍入行為與 ROUND_DOWN 相同。
注意,此舍入模式始終不會減少計算值。
4、ROUND_FLOOR
接近負無窮大的舍入模式。
如果 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;
如果為負,則舍入行為與 ROUND_UP 相同。
注意,此舍入模式始終不會增加計算值。
5、ROUND_HALF_UP
向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為向上舍入的舍入模式。
如果捨棄部分 >= 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同。
注意,這是我們大多數人在小學時就學過的舍入模式(四捨五入)。
6、ROUND_HALF_DOWN
向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為上舍入的舍入模式。
如果捨棄部分 > 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同(五舍六入)。
7、ROUND_HALF_EVEN
向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。
如果捨棄部分左邊的數字為奇數,則舍入行為與 ROUND_HALF_UP 相同;
如果為偶數,則舍入行為與 ROUND_HALF_DOWN 相同。
注意,在重複進行一系列計算時,此舍入模式可以將累加錯誤減到最小。
此舍入模式也稱為“銀行家舍入法”,主要在美國使用。
如果前一位為奇數,則入位,否則捨去。
以下例子為保留小數點1位,那麼這種舍入方式下的結果。
1.15>1.2 1.25>1.2
8、ROUND_UNNECESSARY
斷言請求的操作具有精確的結果,因此不需要舍入。
如果對獲得精確結果的操作指定此舍入模式,則丟擲ArithmeticException。
1、short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 +=1;有什麼錯?
答:對於short s1=1;s1=s1+1來說,在s1+1運算時會自動提升表示式的型別為int,那麼將int賦予給short型別的變數s1會出現型別轉換錯誤。
對於short s1=1;s1+=1來說 +=是java語言規定的運算子,java編譯器會對它進行特殊處理,因此可以正確編譯。
2、char型別變數能不能儲存一箇中文的漢子,為什麼?
char型別變數是用來儲存Unicode編碼的字元的,unicode字符集包含了漢字,所以char型別當然可以儲存漢字的,還有一種特殊情況就是某個生僻字沒有包含在unicode編碼字符集中,那麼就char型別就不能儲存該生僻字。
3、Integer和int的區別
int是java的8種內建的原始資料型別。Java為每個原始型別都提供了一個封裝類,Integer就是int的封裝類。
int變數的預設值為0,Integer變數的預設值為null,這一點說明Integer可以區分出未賦值和值為0的區別,比如說一名學生沒來參加考試,另一名學生參加考試全答錯了,那麼第一名考生的成績應該是null,第二名考生的成績應該是0分。關於這一點Integer應用很大的。Integer類內提供了一些關於整數操作的一些方法,例如上文用到的表示整數的最大值和最小值。
4、switch語句能否作用在byte上,能否作用在long上,能否作用在string上?
byte的儲存範圍小於int,可以向int型別進行隱式轉換,所以switch可以作用在byte上
long的儲存範圍大於int,不能向int進行隱式轉換,只能強制轉換,所以switch不可以作用在long上
string在1.7版本之前不可以,1.7版本之後switch就可以作用在string上了
5.是否存在 x>x+1?為什麼?
這就是臨界值,當x=最大值 時; 再加1(根據二進位制運算+1)就超過了它的臨界值,剛好會是它最小值。
舉個例子吧,byte 8位, -128 ~ 127
127 二進位制: 0111 1111
1 二進位制 : 0000 0001
相加結果: 1000 0000
byte 8位 有符號, 1000 0000 剛好 為 -128
java 基礎–8 種基本資料型別:整型、浮點型、布林型、字元型 整型中 byte、short、int、long 的取值範圍 什麼是浮點型?什麼是單精度和雙精度?為什麼不能用浮點型表示金額?
本作品採用《CC 協議》,轉載必須註明作者和本文連結