1. 程式人生 > 實用技巧 >Java 之 資料型別與型別轉換

Java 之 資料型別與型別轉換

一、資料型別

  1、資料型別分類

    Java 中資料型別分為兩大類:

      基本資料型別:整數、浮點數、字元型、布林型

      引用資料型別(物件型別):類、陣列、字串、介面等。

      

  2、基本資料型別

    四類八種基本資料型別:      

資料型別 關鍵字 記憶體佔用 取值範圍
位元組型 byte 1個位元組 -128~127
短整形 short 2個位元組 -32768~32767
整形 int(預設) 4個位元組 -2的31次方~2的31次方-1
長整型 long 8個位元組 -2的63次方~2的63次方-1
單精度浮點型 float
4個位元組 1.4013E-45~3.4028E+38
雙精度浮點型 double(預設) 8個位元組 4.9E-324~1.7977E+308
字元型 char 2個位元組 0~65535
布林型別 boolean 1個位元組 true、false

二、八種基本資料型別

  1、整數型別

    整數型別:byte、short、int、long

    Java 各整數型別有固定的表示範圍和欄位長度,不受具體OS的影響,以保證Java程式的可移植性。

    Java 的整型常量預設為 int 型,宣告 long 型常量須後加 “l” 或 “L”。

    Java 程式中變數通常宣告為 int 型,除非不足以表達較大的數,才使用 long。

    

    bit:計算機中最小的儲存單位。

    byte:計算機中基本的儲存單元。

    整數用來儲存整數數值,可以是正整數、負數,有3種表示形式:

0B101  // 二進位制
-88    // 十進位制
0123   //八進位制必須以 0 開頭
0x25   // 十六進位制必須以 0X 或 0x 開頭

  

  2、浮點數型別

    浮點數型別:float、double

    與整數型別類似, Java 浮點型別也有固定的表數範圍和欄位長度,不受具體作業系統的影響。

    浮點型常量有兩種表示形式:

      十進位制數形式:如:5.12 512.0f .512(必須有小數點)

      科學計數法形式:如:5.12e2 512E2 100E-2

    float:單精度,位數可以精確到7位有效數字。很多情況下,精度很難滿足需求。

    double:雙精度,精度是 float 的兩倍,通常採用此型別。

    Java 的浮點型常量預設為 double 型,宣告 float 型常量,後面必須加 ‘f’ 或 'F'。

    

    例如:

    

    

    通過上面的程式可以看出,最終的結果並非我們預料的結果,float和double型別運算可能造成精度丟失問題。

  3、字元型別(Java中使用Unicode編碼來表示)

    char 型資料用來表示通常意義上“字元”(2個位元組)

    Java中的所有字元都使用Unicode編碼,故一個字元可以儲存一個字母,一個漢字,或其他書面語的一個字元。

    字串變數的三種表現形式:

      (1)字元常量是用單引號('')括起來的單個字元。

例如: char c1 = 'a'; char c2= '中'; char c3 = '9';

      (2)Java中還允許使用轉義字元 '\' 來將其後的字元轉變為特殊字元常量。

例如: char c3 = ‘\n’; // '\n'表示換行符

      (3)直接使用 Unicode 值來表示字元型常量。

‘\uXXXX’。其中, XXXX代表一個十六進位制整數。如: \u000a 表示 \n。

      常用轉義字元:

      

       Tips:char型別是可以進行運算的。因為它都對應有Unicode碼。

  4、布林型別

    布林型別:boolean

    boolean 型別用來判斷邏輯條件,一般用於程式流程控制。

    boolean 型別資料只允許取值 true 和 false,無 null。

    注意:不可以使用 0 或 非0的整數替代 false 和 true。

    Java虛擬機器中沒有任何供boolean值專用的位元組碼指令, Java語言表達所操作的boolean值,在編譯之後都使用java虛擬機器中的int資料型別來代替: true1表示, false
0表示。 ———java虛擬機器規範 8版》

  5、小結

     (1)Java中的預設型別:整形型別是 int、浮點型別是 double。

    (2)字串不是基本型別,而是引用型別。

    (3)浮點型可能只是一個近似值,並非精確的值。

    (4)資料範圍與位元組數不一定相關,例如float資料範圍比long更加廣泛,但是float是4位元組,long是8位元組。

    (5)浮點數當中預設型別是double。如果一定要使用float型別,需要加上一個字尾F。如果是整數,預設為int型別,如果一定要使用long型別,需要加上一個字尾L。推薦使用大寫字母后綴。

三、資料型別轉換

  型別轉換是從一種型別更改為另一種型別的過程。如果從低精度資料型別向高精度轉換,則永遠不會溢位,總是成功。相反,從高精度向低精度轉換,可能出現資訊丟失,有可能失敗

  1、自動型別轉換(隱式轉換)

    容量小的型別自動轉換為容量大的資料型別。

    資料型別按容量大小排序為:

    

    有多種型別的資料混合運算時,系統首先自動將所有資料轉換成容量最大的那種資料型別,然後再進行計算。

     注意:

      (1)byte、short、char 之間不會相互轉換,他們三者在計算時首先轉換成 int 型別。

      (2)boolean 型別不能與其他資料型別運算。

      (3)當把任何基本資料型別的值和字串(String)進行連線運算時(+),基本資料型別的值將自動轉化為字串(String)型別。

    Demo:

public static void main(String[] args) {
  int i =1;
  byte b = 2;
  // byte x = b + 1;   報錯
  // int型別和 byte 型別運算,結果是 int型別
  int j = b + i;
  System.out.println(j);        
}

    轉換原理圖解:

    byte 型別記憶體佔有1個位元組,在和 int 型別運算會提升為 int 型別,自動補充 3個位元組,因此計算後的結果是 int 型別。

    

    轉換規則:範圍小的型別向範圍大的型別提升,byte、short、char 進行算術運算時直接提升為 int 型別。

    總結

      a、特點:程式碼不需要進行特殊處理,自動完成;

      b、規則:資料範圍從小到大;

  2、強制型別轉換(顯示轉換)

    (1)自動型別轉換的逆過程,將容量大的資料型別轉換為容量小的資料型別。使用時要加上強制轉換符:(),但可能造成精度降低或溢位,格外要注意。

    (2)字串型別不能直接轉換為基本型別,但通過基本型別對應的包裝類則可以實現把字串轉換成基本型別。

如: String a = “43”; int i = Integer.parseInt(a);

    (3)boolean 型別不可以轉換為其他的資料型別。

    強制型別轉換:

資料型別 變數名 = (資料型別) 被轉資料值;

      Demo:

 1 public static void main(String[] args){
 2    // short 型別變數,記憶體中2個位元組
 3    short s = 1;
 4    /*
 5       出現編譯失敗
 6       s 和 1做運算的時候,1是int型別,s 會被提升為 int 型別
 7       s+1 後的結果是 int 型別,將結果在賦值 short 型別時發生錯誤
 8       short  記憶體2個位元組,int  型別4個位元組
 9       必須將 int 強制轉成 short 才能完成賦值  
10    */    
11      s = s + 1;          // 編譯失敗
12      s= (short) (s+1);   // 編譯成功
13 }

    轉換原理圖解:

    注意:

      a、浮點轉成整數,直接取掉小數點,可能造成資料損失精度。

      b、int 強制轉成 short 取掉2個位元組(溢位),可能造成資料丟失。

    總結:

      a、特點:程式碼需要進行特殊的格式處理,不能自動完成。

      b、格式:範圍小的型別 範圍小的變數名 = (範圍小的型別) 原本範圍大的資料;

    注意事項:

      a、強制型別轉換一般不推薦使用,因為有可能發生精度損失、資料溢位。
      b、 byte/short/char 這三種類型都可以發生數學運算,例如加法“+”.
      c、 byte/short/char 這三種類型在運算的時候,都會被首先提升成為int型別,然後再計算。
      d、 boolean 型別不能發生資料型別轉換

  3、 ASCII 編碼表

    字元與數字的對照關係表(編碼表):當有 字元 型別的變數參與運算的時候,會把字元轉變為相應的數字,然後再進行計算。

    

    將所有的英文字母,數字,符號都和十進位制進行了對應,因此產生了世界上第一張編碼表ASCII( American Standard Code for Information Interchange 美國標準資訊交換碼),裡面只有字母數字和常用符號,並沒有漢字。

    Unicode碼錶:萬國碼。也是數字和符號的對照關係,開頭0-127部分和ASCII完全一樣,但是從128開始包含有更多字元。  

    Tips:

     在 char 型別和 int 型別計算的過程中,char 型別的字元先查詢編碼表,得到97,再和1求和,結果為98。char型別提升 為了int型別。char型別記憶體2個位元組,int型別記憶體4個位元組。

四、String 型別

  1、String 不是基本資料型別,屬於引用資料型別。

  2、使用方式與基本資料型別一致。

    例如:

String str = “abcd”;

  3、一個字串可以串接另一個字串,也可以直接串接其他型別的資料。

str = str + “xyz” ;
int n = 100;
str = str + n;

五、擴充套件知識(編譯器的兩點優化)

 1、自動型別轉換問題

    對於byte/short/char三種類型來說,如果右側賦值的數值沒有超過範圍,那麼javac編譯器將會自動隱含地為我們補上一個(byte)(short)(char)。

   (1)如果沒有超過左側的範圍,編譯器補上強轉。

   (2)如果右側超過了左側範圍,那麼直接編譯器報錯。

    Demo:

 1     // 右側確實是一個int數字,但是沒有超過左側的範圍,就是正確的。
 2     // int --> byte,不是自動型別轉換
 3       byte num1 = /*(byte)*/ 30; // 右側沒有超過左側的範圍
 4       System.out.println(num1); // 30
 5         
 6      // byte num2 = 128; // 右側超過了左側的範圍,編譯不通過
 7         
 8      // int --> char,沒有超過範圍
 9       // 編譯器將會自動補上一個隱含的(char)
10         char zifu = /*(char)*/ 65;
11         System.out.println(zifu); // A

  

  2、編譯器的常量優化

   在給變數進行賦值的時候,如果右側的表示式當中全都是常量,沒有任何變數,那麼編譯器javac將會直接將若干個常量表達式計算得到結果。

   short result = 5 + 8; // 等號右邊全都是常量,沒有任何變數參與運算編譯之後,得到的 .class位元組碼檔案當中相當於【直接就是】:short result = 13; (右側的常量結果數值,沒有超過左側範圍,所以正確。)

   注意:一旦表示式當中有變數參與,那麼就不能進行這種優化了。

   Demo:

 1 public static void main(String[] args) {
 2         short num1 = 10; // 正確寫法,右側沒有超過左側的範圍,
 3         
 4         short a = 5;
 5         short b = 8;
 6         // short + short --> int + int --> int
 7         // short result = a + b; // 錯誤寫法!左側需要是int型別,含有兩個變數
 8         
 9         // 右側不用變數,而是採用常量,而且只有兩個常量,沒有其他
10         short result = 5 + 8;
11         System.out.println(result);
12         
13         short result2 = 5 + a + 8; // 18 錯誤,裡面有變數
14 }