java的基本語言元素--常量/變量/基本數據類型

變量與常量是一個Java程序組成的重要部分。

我們可以將變量與常量理解爲數據的載體,而從名稱上我們也可以看出二者的不同:

常量代表不能改變的數據值,而變量的值則存在可變性


在我們回顧Java中的關鍵字的使用時,說道:被Java中的關鍵字final所修飾的變量,其值一經初始化,便不能再次進行賦值。該特性恰恰符合常量的定義。

[java] view plain copy
  1.        String var = "字符串變量";  
  2. //java中,關鍵字final用於聲明數據常量  
  3. final String CONSTANT = "字符串常量";  


既然我們知道了變量與常量是作爲數據的載體使用;那麼,就如同我們如果使用一個杯子作爲載體,那麼其搭載的介質可能是水,咖啡,果汁等等一樣;

我們自然要了解Java中的變量與常量作爲數據載體,其搭載的數據究竟有哪些?

大體來說,Java的數據類型分爲:基本數據類型,對象數據類型以及數組,但數組實際也屬於對象。

所以,Java中的變量/常量就是用以作爲基本數據類型對象數據類型載體的。


對象數據類型的回顧需要結合一個關鍵的概念:類。

所以在這裏,我們先將變量和常量作爲切入點,首先來重新系統的總結一下Java中的8種基本數據類型的特性及使用。

總的來說,Java中的8種數據類型可以分爲三類:數字類型,字符類型和一種特殊的數據類型布爾型。


一、數字數據類型

數字數據類型共有6種,其中4種用於表示整數,2種用於表示浮點數。


首先需要明確的是:Java中的6種數字類型都是有符號數,也就是說它們都有正負之分。而具體又是如何區別表示正數與負數的呢?

我們知道所謂的“1”,“3”,“101”這樣的數,是我們日常生活中習慣使用的十進制數。

但在計算機中,所有數字都是以二進制數來表示的,也就是說,是一串由“0”和“1”組成的數字。

這樣的一串數字中,其最高有效位是用於表示符號的,就是所謂的符號位。

符號位爲“0”,代表是一個正數;符號位爲“1”,代表是一個負數。而剩餘位則用於表示值。


1.1、整數類型

Java中,用於表示整數的4種數字類型分別爲:byte(字節型)、short(短整型)、int(整型)、long(長整形)

我們說在計算機中,數字都是由二進制形式表示的,那麼自然的,其位數越多,可能的取值範圍就越大。

所以我們看到從byte到long,隨着所佔位數的增加,其取值範圍也就越大。

計算機中,一個字節等於8個比特位。而byte長度正是8位,這也是爲什麼它被取名爲字節型;

而剩下的short,int,long分別對應2個字節,4個字節和8個字節。


進制轉換:

我們剛剛已經說到了二進制和十進制,而在Java中,整數還有另外兩種進製表現形式,分別是:八進制和十六進制。

在瞭解進制轉換之前,我們先通過一段簡單的代碼瞭解一下Java中八進制和十六進制數的聲明形式是怎麼樣的:

[java] view plain copy
  1. // 十進制定義形式  
  2. int num_10 = 10;  
  3. // 八進制定義形式,以“0”作爲前綴,表示定義的是一個八進制整數  
  4. int num_8 = 012;  
  5. // 十六進制定義形式,以“0x”作爲前綴,表示定義的是一個十六進制整數  
  6. int num_16 = 0xef;  


瞭解了不同進制的定義形式,我們就可以看一下進制之間的相互轉換了。首先我們應該知道,所謂進制,其實原理都是一樣的:

所謂二進制,就是指“逢二進一”,也就是說二進制中只可能存在“0”和“1”兩種可能值;

而所謂十進制,就是指“逢十進一”,也就是說只可能存在0-9的可能值;

那麼同樣的,八進制就是指“逢八進一”,所以只可能存在0-7的可能值;

同理的,十六進制就存在0-15的可能值。但傳統定義數字中,“9”已經是單位的最大可能值,所以十六進制中以英文字母a - f分別代表 10 - 15。


那麼,進制之間究竟是如何完成相互之間的轉換工作的呢?

1、二進制數、八進制數、十六進制數轉十進制數
有一個公式:二進制數、八進制數、十六進制數的各位數字分別乖以各自的基數的(N-1)次方,其和相加之和便是相應的十進制數。例如:

二進制數:0000-0110轉換爲十進制數:1*2的2次方+1*2的1次方+0*2的0次方=0+4+2+0=6,也就是說轉換爲十進制數的值爲:6。

2、十進制數轉二進制數、八進制數、十六進制數

方法是對應的的,即整數部分用除取餘的算法,小數部分用乘基取整的方法,然後將整數與小數部分拼接成一個數作爲轉換的最後結果。

3、二進制數轉換爲八進制數或十六進制數

其原理很簡單:我們已經知道了八進制只有0-7的可能值,十六進制則只有0-15這的可能值。

而我們觀察到這樣一種情況,對於一個二進制的數來說:

如果只取一個有效位的數,所能能表達的最大數爲:1;

而取兩個有效位的數,所能表達的最大值則爲:“11”,也就是十進制的3;

取三個有效位的數,能表達的最大的數爲“111”,則是十進制的7;

而取四個有效位的數“1111”,則正是十進制的15.


由此我們發現:

如果將二進制數每三位取出,則正好能表示一個八進制的數;

而將二進制數每四位取出,則正好能表示一個十六進制數。


而事實上,二進制與八進制和十六進制的轉換原理也正是這樣的。

舉例來說,以二進制數:0000-1010爲例:

轉換爲八進制數爲:000/001/010,也就是12;

而如果轉換爲十六進制則爲:0000/1010,也就是a。


1.2、浮點數類型

正如數學中數字分爲整數和小數一樣,Java中也是一樣的。但Java不稱爲小數,稱爲浮點數。

而Java中,用於表示浮點數的兩種種數字類型分別爲:float(單精度浮點型)和double(雙精度浮點型)。

Java裏默認的浮點數形式是雙精度形式,也就是double。

所以在定義一個float時,必須加上後綴F(f):float f = 2.3F。

而定義double,後綴D(d)的添加則是可選的。


到了這裏,我們已經瞭解了Java中所有的數字類型。

之所以瞭解它們各自不同的特性,是爲了在實際編寫代碼的過程中,可以根據實際需求選取最合適的數據類型來定義自己的變量(常量)。

舉例來說:

如果想要表示全世界的人口數量,那麼可能選擇long型來表示更爲合適;

而如果要表示某個公司的職員每月的工資情況,那麼選用float可能更爲合適。


三、字符類型

Java中,另一種基本數據類型:char型,代表字符類型。

在開發中,可能經常需要存儲一些字符,如‘A’,‘c’等等。char型就是用於存儲單個字符的數據類型。

同時,char型數據也可以通過Unicode碼錶示字符;

簡單的來說,就是我們也可以通過在Unicode碼錶中有效的整數來表示一個字符。

其實很好理解,就像我們在小時候學習拼音的時候,可能都會接觸到“拼音字母學習表”一樣:

Unicode碼錶也是類似於這樣的一張字符編碼表,所謂編碼就是對錶中的每一個字符編排一個“號碼”。

這個號碼就像我們每個人的身份證,是獨特對應的關係,通過身份證號碼就可以查出我們每個人的信息。

到了這裏就不難理解了,就假設:我們以97表示一個字符,Java會根據該值到Unicode碼錶中進行查詢,然後發現號碼“97”對應的字符是"a"。


Unicode碼是用'\uxxxx'表示的。x表示的是16進制數值。

並且Unicode編碼字符是用16位無符號整數表示的。也就是說,Unicode碼錶共有0-65535的編碼值。


四、布爾類型

Java中一種特殊的數據類型,只有“true”和”false“兩種可能值。通常用於關係運算或條件判斷表達式返回的結果。


數據類型的轉換

Java自身是一門強數據類型語言,所以在遇到不同數據類型同時操作,就需要進行數據類型的轉換。

數據類型轉換需要滿足的最基本的要求,就是數據類型必須兼容。例如要將一個布爾型的數據轉換爲整數類型,肯定是不能成功的。

而在Java中,數據類型的轉換又分爲兩種:自動類型轉換和強制類型轉換。

所謂自動轉換就是指無需認爲做任何額外的工作,虛擬機會自動的完成對數據類型的轉換工作。

而強制轉換則是指我們必須人爲的進行聲明後,才能完成想要的數據類型轉換。

也就是說,自動數據類型轉換是隱式的轉換,而強制類型轉換則是顯式的轉換


那麼首先來看一下自動類型轉換

第一種情況:低位數的數據類型可以自動轉換爲高位數的數據類型。

[java] view plain copy
  1. // 低位數的數據類型自動轉換爲高位數的數據類型  
  2. byte b = 1;  
  3. short s = b;  
  4. int i = s;  
  5. long l = i;  
  6. float f = 1.5f;  
  7. double d = f;  
  8. /* 
  9.  * 另外,Java中整數的默認形式爲int型,  
  10.  * 所以下面的聲明形式實際也是:  
  11.  * 虛擬機自動完成了一次隱式的數據轉換工作 
  12.  */  
  13. long num = 1000;  

第二種情況:整數類型可以自動轉爲浮點數類型,但是這種轉換後的值可能會出現誤差。

第三種情況:字符類型可以自動轉換爲整型或長整形。這是因爲Java中char型數據也可以通過Unicode碼錶示,長度爲16位,所以也可以轉換爲長度更大的int和long型。

[java] view plain copy
  1. char c1 = 'a';  
  2. int i1= c1;  
  3.   
  4. char c2 = 'b';  
  5. int i2 = c2 + 10;  
  6.   
  7. char c3 = 'c';  
  8. long l = c3;  

接下來,就是Java中的強制類型轉換:強制轉換的格式爲:(type)value。

第一種情況:對應於自動轉換,那麼當高位數的數據類型轉換爲低位數的數據類型時,就需要做強制轉換。


既然我們看到了”強制",那可能我們自然就會想到在這樣的轉換過程中,是不是存在一定的“風險”?

Java自身是一門嚴謹的編程語言,如果不存在風險,爲何還需要我們作人爲的"強制“性轉換呢?

而事實上也正是如此。我們首先應當瞭解,Java中對一個高位數數據轉換爲低位數數據類型時,實際上是在對二進制表現形式做有效位的截取。

我們知道一個二進制數的位數越多,其取值範圍也就越大,也就是說它的可能值越多。

這也就意味着,如果將一個高位數的數據類型轉換爲低位數的數據類型,那麼便可能發生:很多高位數能夠表達的可能值,低位數表達不了的情況。

這也正是其”風險“所在:轉換的過程中,可能造成數據丟失!


我們舉個例子來說:

假設我們有一個int型的變量,值爲128。相應的,我們將其轉換爲二進制表現形式就是:0000 0000 - 0000 0000 - 0000 0000 - 1000 0000。

如果我們要將其轉換爲byte類型。那麼byte類型的數據長度爲8位,所以我們進行有效位的截取後,值變爲了:1000 0000。

我們知道二進制數的最高有效位用以表示符號,所以這裏轉後的值的實際值變爲了十進制當中的-128。所以128在這個轉換中,值由原本的128變爲了-128。


既然高位數數據類型轉換低位數數據類型存在這樣的風險,那麼作爲一門健壯的語言,Java自然是不支持這樣的轉換的。

所以,爲我們了提供了(type)value這樣的強制轉換方式,我們這樣做的意義就在於,告訴編譯器,我瞭解這樣做可能承擔風險,但這個風險由我來承擔。

最後,我們通過代碼來驗證我們剛剛的轉換過程:

[java] view plain copy
  1.            int i1 = 127;  
  2.            byte b1 = (byte) i1;  
  3.            System.out.println("b1="+b1);  
  4.              
  5.            int i2 = 128;  
  6.            byte b2 = (byte) i2;  
  7.            System.out.println("b2="+b2);  

其運行的輸出結果爲:

b1=127

b2=-128

通過其結果恰恰驗證了我們提到的轉換過程。

因爲127本身在byte的取值範圍之內,所以強制轉換過後,數據仍然正確。但128超出了byte的取值範圍,所以在經過有效位的截取之後,值發生了變化,變爲了-128.


第二種情況:浮點數類型轉換爲整數類型需要進行強制轉換,因爲小數點後的數在轉換過程中會被丟棄

[java] view plain copy
  1. double d = 128.123;  
  2. //轉換後的值變爲了128  
  3. int i = (int) d;  
  4. System.out.println(i);  


到此,我們以Java的變量(常量)爲切入點,又重新回顧了Java中8種基本數據類型的特點和使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章