Java語言是靜態類型的(statical typed),也就是說全部變量和表達式的類型再編譯時就已經徹底肯定。因爲是statical typed,致使Java語言也是強類型(Strong typed)的。強類型意味着每一個變量都具備一種類型,每一個表達式具備一種類型,而且每種類型都是嚴格定義的,類型限制了變量能夠hold哪些值,表達式最終產生什麼值。同時限制了這些值能夠進行的操做類型以及操做的具體方式。全部的賦值操做,不管是顯式的仍是在方法調用中經過參數傳遞,都要進行類型兼容性檢查。html
在java源代碼中,每一個變量都必須聲明一種類型(type)。有兩種類型:primitive type和reference type。引用類型引用對象(reference to object),而基本類型直接包含值(directly contain value)。所以,Java數據類型(type)能夠分爲兩大類:基本類型(primitive types)和引用類型(reference types)。primitive types 包括boolean類型以及數值類型(numeric types)。numeric types又分爲整型(integer types)和浮點型(floating-point type)。整型有5種:byte short int long char(char本質上是一種特殊的int)。浮點類型有float和double。關係整理一下以下圖:java
對象是動態建立的類實例或者動態建立的數組。The value of reference types are references to objects,而引用通常是指內存地址。全部的對象(包括數組)支持Object類中定義的方法。String literals are presented by String object.數組
java有兩種類型(type),與之相對應的是兩種數據的值(two kinds of data values that can be stored in variable, pass as arguments and returned by methods),這兩隻data values是:primitive values,reference values。也許這麼理解起來更方便(雖然不嚴謹),Java變量有兩種:primitive variable和reference variable,在變量中,它們分別存儲primitive value和reference value。網絡
null是一種特殊的type,可是你不能聲明一個變量爲null類型,null type的惟一取值就是null。null能夠負值給任意的引用類型或者轉化成任意的引用類型。在實踐中,通常把null當作字面值(literal),這個字面值但是是任意的引用類型。oracle
Java爲基本類型提供語言級別的支持,即已經在Java中預約義,用相應的保留關鍵字表示。基本類型是單個值,而不是複雜的對象,基本類型不是面向對象的,主要出去效率方面的考慮,可是同時也提供基本類型的對象版本,即基本類型的包裝器(wrapper)。能夠直接使用這些基本類型,也可使用基本類型構造數組或者其餘自定義類型。基本類型具備明確的取值範圍和數學行爲。app
整型有byte short int long char,分別用八、1六、3二、6四、16bits表示。有些地方可能不會把char列入整型範疇,但本質上char類型是int的一個子集。整型的寬度不該該被當作整數所佔用的內存空間大小,而應當理解成定義爲整型的變量或者表達式的行爲。JVM能夠自由使用它們但願的、任何大小的內存空間,只要類型的行爲符合規範。byte short int long都是有符號的,用2的補碼(two‘s-complement)表示。而char用16位表示,它是無符號的,表示的是UTF-16編碼集。ide
byte由1個字節8位表示,是最小的整數類型。主要用於節省內存空間關鍵。當操做來自網絡、文件或者其餘IO的數據流時,byte類型特別有用。取值範圍爲:[-128, 127]. byte的默認值爲(byte)0,若是咱們試圖將取值範圍外的值賦給byte類型變量,則會出現編譯錯誤,例如 byte b = 128;這個語句是沒法經過編譯的。一個有趣的問題,若是咱們有個方法: public void test(byte b)。試圖這麼調用這個方法是錯誤的: test(0); 編譯器會報錯,類型不兼容!!!咱們記得byte b =0;這是徹底沒有問題的,爲何在這裏就出錯啦?函數
這裏涉及到一個叫字面值(literal)的問題,字面值就是表面上的值,例如整型字面值在源代碼中就是諸如 5 , 0, -200這樣的。若是整型子面子後面加上L或者l,則這個字面值就是long類型,好比:1000L表明一個long類型的值。若是不加L或者l,則爲int類型。基本類型當中的byte short int long均可以經過不加L的整型字面值(咱們就稱做int字面值吧)來建立,例如 byte b = 100; short s = 5;對於long類型,若是大小超出int所能表示的範圍(32 bits),則必須使用L結尾來表示。整型字面值能夠有不一樣的表示方式:16進制【0X or 0x】、10進制【nothing】、八進制【0】2進制【0B or 0b】等,二進制字面值是JDK 7之後纔有的功能。在賦值操做中,int字面值能夠賦給byte short int long,Java語言會自動處理好這個過程。若是方法調用時不同,調用test(0)的時候,它能匹配的方法是test(int),固然不能匹配test(byte)方法,至於爲何Java沒有像支持賦值操做那樣支持方法調用,不得而知。注意區別包裝器與原始類型的自動轉換(anto-boxing,auto-unboxing)。byte d = 'A';也是合法的,字符字面值能夠自動轉換成16位的整數。編碼
更多關於字面值的介紹,參考oracle文檔(http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html)。spa
對byte類型進行數學運算時,會自動提高爲int類型,若是表達式中有double或者float等類型,也是自動提高。因此下面的代碼是錯誤的:
[java] view plaincopy
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">byte t s1 = 100;
byte s2 = 'a';
byte sum = s1 + s2;//should cast by (byte)</span></span></span>
用16爲表示,取值範圍爲:[- 2^15, 2^15 - 1]。short多是最不經常使用的類型了。能夠經過整型字面值或者字符字面值賦值,前提是不超出範圍(16 bit)。short類型參與運算的時候,同樣被提高爲int或者更高的類型。(順序爲 byte short int long float double).
32 bits, [- 2^31, 2^31 - 1].有符號的二進制補碼錶示的整數。經常使用語控制循環,注意byte 和 short在運算中會被提高爲int類型或更高。Java 8之後,可使用int類型表示無符號32位整數[ 0, 2^31 - 1]。
64 bits, [- 2^63, 2^63 - 1,默認值爲0L].當須要計算很是大的數時,若是int不足以容納大小,可使用long類型。若是long也不夠,可使用BigInteger類。
16 bits, [0, 65535], [0, 2^16 -1],從'\u0000'到'\uffff'。無符號,默認值爲'\u0000'。Java使用Unicode字符集表示字符,Unicode是徹底國際化的字符集,能夠表示所有人類語言中的字符。Unicode須要16位寬,因此Java中的char類型也使用16 bit表示。 賦值多是這樣的:
char ch1 = 88;
char ch2 = 'A';
ASCII字符集佔用了Unicode的前127個值。之因此把char納入整型,是由於Java爲char提供算術運算支持,例如能夠ch2++;以後ch2就變成Y。當char進行加減乘除運算的時候,也被轉換成int類型,必須顯式轉化回來。
包含單精度的float和雙精度的double,分別用3二、64bits表示,遵循IEEE 754規範。
使用32 bit表示,對應單精度浮點數,運行速度相比double更快,佔內存更小,可是當數值很是大或者很是小的時候會變得不精確。精度要求不高的時候可使用float類型,聲明賦值示例:
[java] view plaincopy
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">float f1 =10;
f1 = 10L;
f1 = 10.0f;
//f1 = 10.0;默認爲double</span></span></span>
能夠將byte、short、int、long、char賦給float類型,java自動完成轉換。
64爲表示,將浮點子面子賦給某個變量時,若是不顯示在字面值後面加f或者F,則默認爲double類型。java.lang.Math中的函數都採用double類型。
若是double和float都沒法達到想要的精度,可使用BigDecimal類。
boolean類型只有兩個值true和false,默認爲false。boolean與是否爲0沒有任何關係,可是能夠根據想要的邏輯進行轉換。許多地方都須要用到boolean類型。
在Java源代碼中,字面值用於表示固定的值(fixed value)。數值型的字面值是最多見的,字符串字面值能夠算是一種,固然也能夠把特殊的null當作字面值。字面值大致上能夠分爲整型字面值、浮點字面值、字符和字符串字面值、特殊字面值。
從形式上看是整數的字面值歸類爲整型字面值。例如: 10, 100000L, 'B'、0XFF這些均可以稱爲字面值。整型字面值能夠用十進制、1六、八、2進制來表示。十進制很簡單,二、八、16進制的表示分別在最前面加上0B(0b)、0、0X(0x)便可,固然基數不能超出進制的範圍,好比09是不合法的,八進制的基數只能到7。通常狀況下,字面值建立的是int類型,可是int字面值能夠賦值給byte short char long int,只要字面值在目標範圍之內,Java會自動完成轉換,若是試圖將超出範圍的字面值賦給某一類型(好比把128賦給byte類型),編譯通不過。而若是想建立一個int類型沒法表示的long類型,則須要在字面值最後面加上L或者l。一般建議使用容易區分的L。因此整型字面值包括int字面值和long字面值兩種。
浮點字面值簡單的理解能夠理解爲小數。分爲float字面值和double字面值,若是在小數後面加上F或者f,則表示這是個float字面值,如11.8F。若是小數後面不加F(f),如10.4。或者小數後面加上D(d),則表示這是個double字面值。另外,浮點字面值支持科學技術法表示。下面是一些例子:
[java] view plaincopy
<span style="font-family:Microsoft YaHei;font-size:14px;">double d1 = 10;
double d2 = 11.4;
double d3 = 1.23E3;
double d4 = 10D;
double d5 = 0.4D;
float f1 = 10;
float f2 = 11.1F;
float f3 = 1.23e-4F;
float f4 = 1.23E0F;</span>
Java中字符字面值用單引號括起來,如‘@’‘1’。全部的UTF-16字符集都包含在字符字面值中。不能直接輸入的字符,可使用轉義字符,如‘\n’爲換行字符。也可使用八進制或者十六進制表示字符,八進制使用反斜槓加3位數字表示,例如'\141'表示字母a。十六進制使用\u加上4爲十六進制的數表示,如'\u0061'表示字符a。也就是說,經過使用轉義字符,能夠表示鍵盤上的有的或者沒有的全部字符。常見的轉義字符序列有:
\ddd(八進制) 、 \uxxxx(十六進制Unicode字符)、\'(單引號)、\"(雙引號)、\\ (反斜槓)\r(回車符) \n(換行符) \f(換頁符) \t(製表符) \b(回格符)
字符串字面值則使用雙引號,字符串字面值中一樣能夠包含字符字面值中的轉義字符序列。字符串必須位於同一行或者使用+運算符,由於java沒有續行轉義序列。
null是一種特殊的類型(type),能夠將它賦給任何引用類型變量,表示這個變量不引用任何東西。若是一個引用類型變量爲null,表示這個變量不可用。
還有一種特殊的class literal,用type name加上.class表示,例如String.class。首先,String是類Class(java.lang.Class)的一個實例(對象),而"This is a string"是類String的一個對象。而後,class literal用於表示類Class的一個對象,好比String.class用於表示類Class的對象String。簡單地說,類子面子(class literal)就是諸如String.class 、Integer.class這樣的字面值,它所表示的就是累String、類Integer。若是輸出Integer.class,你會獲得class java.lang.Integer。List.class的輸出爲interface java.util.List。總之,class literal用於表示類型自己!
JDK7開始,能夠在數值型字面值(包括整型字面值和浮點字面值)插入一個或者多個下劃線。可是下劃線只能用於分隔數字,不能分隔字符與字符,也不能分隔字符與數字。例如 int x = 123_456_789.在編譯的時候,下劃線會自動去掉。能夠連續使用下劃線,好比float f = 1.22___33__44.二進制或者十六進制的字面值也可使用下劃線,記住一點,下劃線只能用於數字與數字之間,初次之外都是非法的。例如1._23是非法的,_12三、11000_L都是非法的。
咱們看到,將一種類型的值賦給另外一種類型是很常見的。在Java中,boolean類型與全部其餘7種類型都不能進行轉換,這一點很明確。對於其餘7中數值類型,它們之間均可以進行轉換,可是可能會存在精度損失或者其餘一些變化。轉換分爲自動轉換和強制轉換。對於自動轉換(隱式),無需任何操做,而強制類型轉換須要顯式轉換,即便用轉換操做符(type)。首先將7種類型按下面順序排列一下:
byte <(short=char)< int < long < float < double
若是從小轉換到大,能夠自動完成,而從大到小,必須強制轉換。short和char兩種相同類型也必須強制轉換。
自動轉換時發生擴寬(widening conversion)。由於較大的類型(如int)要保存較小的類型(如byte),內存老是足夠的,不須要強制轉換。若是將字面值保存到byte、short、char、long的時候,也會自動進行類型轉換。注意區別,此時從int(沒有帶L的整型字面值爲int)到byte/short/char也是自動完成的,雖然它們都比int小。在自動類型轉化中,除了如下幾種狀況可能會致使精度損失之外,其餘的轉換都不能出現精度損失。
》int--> float
》long--> float
》long--> double
》float -->double without strictfp
除了可能的精度損失外,自動轉換不會出現任何運行時(run-time)異常。
若是要把大的轉成小的,或者在short與char之間進行轉換,就必須強制轉換,也被稱做縮小轉換(narrowing conversion),由於必須顯式地使數值更小以適應目標類型。強制轉換採用轉換操做符()。嚴格地說,將byte轉爲char不屬於narrowing conversion),由於從byte到char的過程實際上是byte-->int-->char,因此widening和narrowing都有。強制轉換除了可能的精度損失外,還可能使模(overall magnitude)發生變化。強制轉換格式以下:
(target-type) value
[java] view plaincopy
<span style="font-family:Microsoft YaHei;font-size:14px;">int a=257;
byte b;
b = (byte)a;//1</span>
若是整數的值超出了byte所能表示的範圍,結果將對byte類型的範圍取餘數。例如a=256超出了byte的[-128,127]的範圍,因此將257除以byte的範圍(256)取餘數獲得b=1;須要注意的是,當a=200時,此時除了256取餘數應該爲-56,而不是200.
將浮點類型賦給整數類型的時候,會發生截尾(truncation)。也就是把小數的部分去掉,只留下整數部分。此時若是整數超出目標類型範圍,同樣將對目標類型的範圍取餘數。
7中基本類型轉換總結以下圖:
在使用字面值對整數賦值的過程當中,能夠將int literal賦值給byte short char int,只要不超出範圍。這個過程當中的類型轉換時自動完成的,可是若是你試圖將long literal賦給byte,即便沒有超出範圍,也必須進行強制類型轉換。例如 byte b = 10L;是錯的,要進行強制轉換。
除了賦值之外,表達式計算過程當中也可能發生一些類型轉換。在表達式中,類型提高規則以下:
》全部byte/short/char都被提高爲int。
》若是有一個操做數爲long,整個表達式提高爲long。float和double狀況也同樣。