1. 程式人生 > 實用技巧 >Java面向物件程式設計-資料型別和變數

Java面向物件程式設計-資料型別和變數

第三章 資料型別和變數

程式的基本功能就是處理資料,程式用變量表示資料。

在程式中,必須先定義變數,才能使用它。

定義變數指的是設定變數的資料型別和變數的名字。

定義變數的基本語法為:

資料型別名 變數名

例如:

int result = 1;

以上程式碼中的“=”為賦值運算子,用於把右邊表示式的值賦給左邊的變數。

Java語言把資料型別分為基本型別和引用型別:

基本型別:

  • 數值型別
    • 浮點數型別
      • float
      • double
    • 整數型別
      • byte
      • short
      • int
      • long
      • char
  • boolean

引用型別:

  • 引用
    • 類型別
    • 介面型別
    • 陣列型別

3.1 基本資料型別

基本資料型別的取值範圍:

資料型別 關鍵字 在記憶體中佔用的位元組數 取值範圍 預設值
布林型 boolean 1個位元組(8位) true,false false
位元組型 byte 1個位元組(8位) -127~128 0
字元型 char 2個位元組(16位) 0~2^16-1 '\u0000'
短整型 short 2個位元組(16位) -215~215-1 0
整型 int 4個位元組(32位) -231~231-1 0
長整型 long 8個位元組(64位) -263~263-1 0
單精度浮點型 float 4個位元組(32位) 1.4013E-45~3.4028e+38 0.0F
雙精度浮點型 double 8個位元組(64位) 4.9E-324~1.7977E+308 0.0D
3.1.1 boolean型別

boolean型別的變數的取值只能是true或false

Java虛擬機器對boolean型別的處理比較特別。

當Java編譯器把Java原始碼編譯為位元組碼時,會用int或byte來表示boolean。在Java虛擬機器中,用整數零來表示false,用任意一個非零整數來表示true。

在Java源程式中,不允許把整數或null賦值給boolean型別的變數。

3.1.2 byte、short、int和long型別

這四種類型都是整數型別,並且都是有符合整數。

  • 有符號數:把二進位制的首位作為符號位,當首位時零時,對應10進位制的正整數,當首位是1時,對應十進位制的負整數。對於1個位元組的二進位制數,對應十進位制的整數的範圍是-128~127
  • 無符號整數:把二進位制的所有位轉換為正整數。對於1個位元組的二進位制數,對應十進位制數的取值範圍是0~256
  1. 選擇合適的整數型別:

在定義一個變數時,到底要選用哪種資料型別,需要同時考慮實際需求和程式的效能。

在Java語言中,如果數學表示式中都是整數,那麼表示式的返回值只能是long或int型別,如果把返回值賦給byte型別,則必須進行強制型別轉換。

  1. 給整數型別變數賦值

如果一個整數值在某種整數型別的取值範圍內,就可以直接賦值給這種型別的變數,否則必須進行強制型別轉換。

Java語言允許把二進位制(以0b開頭)、八進位制(以0開頭)、十六進位制(以0x開頭)和十進位制數賦給整數型別變數。

  1. 用符合“_”分割數字,提高可讀性。

例如:

int a = 1000000;
int a = 1_000_000;

以上程式碼作用完全相同,區別在於第二段程式碼具有更好的可讀性。可以清晰的看到數字的長度。

3.1.3 char型別與字元編碼

char是字元資料型別,Java語言對字符采用Unicode字元編碼。

常見的字元編碼包括:

  • ASCII編碼
  • ISO-8859-1編碼
  • GB2312編碼
  • GBK編碼
  • Unicode編碼
  • UTF編碼

Java語言採用UCS-2編碼,字元佔兩個位元組。

Java語言把字元同時作為無符號整數對待,取值範圍是0~2^16-1

常見的轉義字元:

轉義字元 描述
\n 換行符,將游標定位在下一行的開頭
\t 垂直製表符,將游標移到下一個製表符的位置
\r 回車,將游標定位在當前行的開頭,不會跳到下一行
\\ 代表反斜槓字元
\' 代表單引號字元
\" 代表雙引號字元
3.1.4 float和double型別

Java語言支援兩種浮點型別的小數

  • float:佔4個位元組,共32位,稱為單精度浮點數
  • double:佔8個位元組,共64位,稱為雙精度浮點數

3.2 引用型別

引用型別可分為:類引用型別,介面引用型別和陣列引用型別。

以下程式碼定義了3個引用變數:

Doll doll;
java.lang.Runnable myThread;
int[] intArray;
  • doll變數位類引用型別,引用這個類或其子類的例項
  • myThread變數為介面引用型別,引用實現了這個介面的類的例項
  • intArray變數為陣列引用型別,引用這個陣列型別的例項

注意:在Java中,陣列也被看作物件,所以說,不管何種引用型別的變數,它們引用的都是物件

3.2.1 基本型別和引用型別的區別
  • 基本型別代表簡單的資料型別,引用型別所引用的例項能表示任意一種複雜的資料結構。
  • 基本型別僅表示資料型別,而引用型別所引用的例項除了表示複雜資料型別,還能包括操作這種資料型別的行為。
  • Java虛擬機器處理引用型別變數和基本型別的方式不一樣:對於基本型別的變數,Java虛擬機器會為其分配資料型別實際佔用的記憶體大小,而對於引用型別變數,它僅僅是一個指向堆區中的某個例項的指標。
3.2.2 用new關鍵字建立物件

當一個引用型別的變數被聲明後,如果沒有初始化,那麼它不指向任何物件。

Java語言用new關鍵字建立物件,它有以下作用:

  • 為物件分配記憶體空間,將物件的例項變數自動初始化為其變數型別的預設值。
  • 如果例項變數在宣告時被顯式初始化,那就把初始化值賦給例項變數。
  • 呼叫構造方法
  • 返回物件的引用

3.3 變數的作用域

變數的作用域是指它的存在範圍,只有在這個範圍內,程式程式碼才能訪問它。

變數的作用域決定了變數的生命週期,變數的生命週期是指從一個變數被建立並分配記憶體空間開始,到這個變數被銷燬並清除記憶體的過程。

按照作用域的不同,變數可分為以下型別:

  • 成員變數:在類中宣告,作用域整個類
  • 區域性變數:在一個方法的內部或方法的一個程式碼塊的內部宣告。如果在一個方法內宣告,則作用域為整個方法,如果在一個方法的某個程式碼塊的內部宣告,則作用域是這個程式碼塊(程式碼塊是指一對大括號內的程式碼)
  • 方法引數:方法或者構造方法的引數,它的作用域是整個方法或構造方法
  • 異常處理引數:是指catch(Exception e)語句中的異常引數e,作用域是緊跟catch語句後面的程式碼塊。

成員變數可以在類中的方法外的任何地方定義,而區域性變數必須先定義後使用。

3.3.1 例項變數和靜態變數的生命週期

類的成員變數有兩種,一種是被static關鍵字修飾的變數,叫類變數,或靜態變數;一種是沒有static修飾的變數,叫例項變數。

  • 類的靜態變數在記憶體中只有一個,Java虛擬機器在載入類的過程中為靜態變數分配記憶體,靜態變數位於方法區。被類的所有例項共享。靜態變數可直接通過類名訪問。靜態變數的生命週期取決於類的宣告週期,當載入類的時候,靜態變數被建立並分配記憶體,當解除安裝類的時候,靜態變數被消耗並撤銷記憶體。

  • 類的每個例項都有相應的例項變數。每建立一個類的例項,Java虛擬機器就會為例項變數分配一次記憶體,例項變數位於堆區中,例項變數的生命週期取決於例項的宣告週期,當建立例項的時候,例項變數被建立並分配記憶體;當銷燬例項的時候,例項變數被銷燬並撤銷記憶體。

    靜態變數可以作為所有例項的共享資料,它不依賴於特定的例項;而例項變數屬於特定的例項。

3.3.2 區域性變數的生命週期

區域性變數的生命週期取決於方法何時被呼叫及結束呼叫。

  • 當Java虛擬機器(確切的說,是Java虛擬機器中的某個執行緒)呼叫一個方法時,會為這個方法的區域性變數分配記憶體。
  • 當Java虛擬機器結束呼叫一個方法時,會結束這個方法中區域性變數的生命週期。
3.3.3 成員變數和區域性變數同名

在同一個作用域內不允許定義同名的多個變數。

在一個方法內,可以定義和成員變數同名的區域性變數和方法引數,此時成員變數被遮蔽。如果要訪問例項變數,可以使用this關鍵字。this為當前例項的引用。如果要訪問類變數,可以通過類名訪問。

3.3.4 將區域性變數的作用域最小化

將區域性變數的作用域最小化可以增加程式碼的可讀性和 可維護性,並且降低出錯的可能性。

將區域性變數的作用域最小化,應該遵守以下規則

  • 在需要使用某區域性變數時,才定義它。
  • 使方法小而集中。如果一個方法包含多種操作,儘可能把這個方法分解為多個小方法,每個方法負責一項操作。

3.4 物件的預設引用:this

當一個變數建立好後,Java虛擬機器就會給他分配一個引用自身的指標:this。所有物件預設的引用名均為this。

在程式中,以下情況會使用this關鍵字:

  • 在類的構造方法中,通過this關鍵字呼叫這個類的另一個構造方法
  • 在一個類的例項中,區域性變數或引數和例項變數同名,例項變數被遮蔽
  • 在一個例項方法內,訪問當前例項的引用

注意:只能在構造方法或例項方法中使用this關鍵字,而在靜態方法和靜態程式碼塊內不能使用this關鍵字

3.5 引數傳遞

如果方法A呼叫方法B,那麼稱方法A是方法B的呼叫者。如果方法B的引數是基本資料型別,那麼方法A向方法B傳遞引數的值;如果方法B的引數是陣列或物件,那麼方法A向方法B傳遞物件或陣列的引用。

3.6 變數的初始化和預設值

程式中的變數用域表現現實系統中的某種資料。

Java語言要求變數遵循先定義,初始化再使用的規則。

變數的初始化是指自從定義變數以後,首次給它賦值的過程。

3.6.1 成員變數的初始化

對於類的成員變數,不管程式有沒有顯式的進行初始化,Java虛擬機器會自動給它初始化為預設值。

3.6.2 區域性變數的初始化

區域性變數宣告之後,Java虛擬機器不會自動給它初始化為預設值。因此區域性變數必須顯式初始化。

如果區域性變數沒有初始化,並且在方法中一直沒有被使用,編譯和執行都會通過

3.7 直接數

直接數是指直接賦給變數的具體數值。

3.7.1 直接數的型別
  • int型直接數
  • long型直接數
  • float型直接數
  • double型直接數
  • boolean型直接數
  • char型直接數
  • String型直接數

Java的直接數具有以下特點:

  • 對於基本資料型別,除了byte和short型別,都有相應的直接數
  • 對於整數,如果在int型別的取值範圍內,就是int型直接數;如果在long型別的範圍內,就是long型直接數。
  • 對於long、float和double型直接數,可以分別加上字尾L、F或D
  • 如果一個小數沒有任何字尾,那麼它是double型直接數
  • 對於引用型別,只有String型別具有直接數
  • String型別和char型別的直接數的區別是:前者表示字串,位於雙引號內,後者表示字元,位於單引號內。
3.7.2 直接數的賦值

直接數的賦值具有以下特點:

  • 基本型別直接數不允許賦值給String型別變數,反之亦然。
  • boolean型別的直接數只能賦值給boolean型別,boolean型別的變數只接受boolean型別的直接數。
  • 把int型別的直接數賦值給byte、short或char型別的變數時,如果直接數的值位於該變數的取值範圍內,就允許直接賦值;否則必須進行強制型別轉換。
  • 把float型別和double型別直接數賦值給整型變數時,必須進行強制型別轉換;而把整型直接數賦值給float或double型別變數時,允許直接賦值。
  • 把double型直接數賦值給float型別時,必須經過強制型別轉換;把float直接數賦值給double型別時,可以直接賦值。