1. 程式人生 > 其它 >第三章:資料型別、變數和陣列

第三章:資料型別、變數和陣列

package com.alanliu.Java8BasicCodeStuding.Java8BasciCode.Unit3;

/**
   第三章:資料型別、變數和陣列

本章分析Java中最基本的3個元素:資料型別、變數與陣列。
與所有現代程式語言一樣,Java支援好幾種類型的資料。
可以使用這些型別宣告變數並建立陣列。
正如您將會看到的,Java支援這些元素的方式是清晰、高效並且內聚的。il“立他奇”全聯幹H缺亞3


 Java是一種強型別化的語言,在開始時指出這一點是很重要的。實際上,Java的安全性和健壯性正是部分來自這一事實。強型別化意味著什麼呢?
 首先,每個變數具有一種型別,
 每個表示式具有一種型別,並且每種型別都是嚴格定義的。其次,所有賦值,不管是顯式的還是在方法呼叫中通過引數傳遞的,都要進行型別相容性檢查。
 在有些語言中,則不對存在衝突的型別進行自動強制轉換。
 Java編譯器檢查所有表示式和引數,以確保型別是相容的。任何型別不匹配都是錯誤,在編譯器完成類的編譯之前必須改正這些錯誤。


Java定義了8種基本資料型別: byte、short、int、long、char、float、double和 boolean。
基本型別通常也稱為簡單型別,開且在個nt 和 long,它們用於表示有符號整數。
·整型這一組包括byte、short、int 和 long,它們用於表示有符號整數。
浮點型這一組包括float 和 double,它們表示帶小數位的數字。
·字元型這一組包括char,表示字符集中的符號,比如字母和數字。
·布林型這一組包括boolean,是一種用於表示 true/false值的特殊型別。
可以直接使用這些型別,也可以使用它們構造陣列以及自定義型別。因此,它們形成了所有可以建立的其他型別的基礎。
基本型別表示單個值——而不是複雜物件。儘管Java在其他方面是完全面向物件的,但是基本型別不是面向物件的。
它們與大多數其他非面嚮物件語言中的簡單型別類似。這樣設計的原因是效率。將基本型別設計成物件會極大地降低效能。
基本型別被定義為具有明確的範圍和數學行為。C和C++這類語言允許整數的大小隨著執行環境的要求而變化。
然而,Java 與小內四a int 總是32位的,因而可以編寫出都具有嚴格定義的範圍。例如,無論在哪種特定平臺上,int總是32位的,
因而可以編寫出不經修改就能確保在任何體系結構的計算機上都能執行的程式。雖然嚴格指定整數的範圍在某些環境中可能會造成一些效能損失,但為了實現可移植性這麼做是必要的。
下面依次分析每種資料型別。





Java定義了4種整數型別: byte、short、int和 long。所有這些型別都是有符號的.
正的或負的整數。Java不支援無符號的、只是正值的整數。許多其他計算機語言同時支援有符號和無符號的。




整數型別的寬度和範圍:
名稱    寬度   範圍
long   64    -9223372 036 854 775 808~9 223 372 036 854 775 807
int    32    -2147 483648~2147 483647
short  16    -32768~32 767
byte   8     -128~127


3.3.1byte
	最小的整數型別是byte。它是有符號的8位型別,範圍為-128~127。
	當操作來自網路或檔案的資料流時,byte型別的變數特別有用。
	當操作與Java 的其他內建型別不直接相容的原始二進位制資料時,byte型別的變數也很有用。
	位元組變數是通過關鍵字byte宣告的。例如,下面聲明瞭兩個byte變數b和c:
	byte b, c;

3.3.2short
	short是有符號的16位型別。它的範圍為-32768~32767。它可能是最不常用的Java型別。
	下面是宣告short變數的一些例子:short s;H short t;

3.3.3 int
	最常用的整數型別是int。它是有符號的32位型別,範圍為-2147483648~2147 483 647。
	除了其他用途外, int型別變數通常用於控制迴圈和索引陣列。
	對於那些不需要更大範圍的 int型別數值的情況,您可能會認為使用範圍更小的 byte和 short型別效率更高,然而事實並非如此。
	原因是如果在表示式中使用byte和 short值,當對錶達式求值時它們會被提升(promote)為int型別(型別提升將在本章後面描述)。
	所以,當需要使用整數時,int通常是最好的選擇。
3.3.4 long
	long 是有符號的64位型別,對於那些int型別不足以容納期望數值的情況,long型別是有用的。
	long型別的範圍相當大,這使得當需要很大的整數時它非常有用。
	例如,下面的程式計算光在指定的天數中傳播的距離(以英里為單位):

浮點型:
	浮點數也稱為實數(real number),當計算需要小數精度的表示式時使用。
	例如,求平方根這類計算以及正弦和餘弦這類超越數,儲存結果就需要使用浮點型別。
	Java實現了IEEE-754標準集的浮點型別和運算子。有兩種浮點型別——float和 double,它們分別表示單精度和雙精度浮點數。它們的寬度和範圍如表3-2所示。
	=======================================================
	     表3-2浮點型的寬度和範圍
	-------------------------------------------------------
	  名稱       寬度   範圍
	  double    64    4.9e-324~1.8e+308
	  float     32    1.4e-045~3.4e+038

float
	float型別表示使用32位儲存的單精度(single-precision)數值。
	在某些處理器上,單精度運算速度更快,並且佔用的空間是雙精度的一半,但是當數值非常大或非常小時會變得不精確。
	如果需要小數部分,並且精度要求不是很高時,float型別的變數是很有用的。例如,表示美元和美分時可以使用float型別。
	下面是宣告float變數的一些例子:  float hightemp,lowtemp;

double
    雙精度使用double關鍵字表示,並使用64位儲存數值。在針對高速數學運算進行了優化的某些現代處理器上,實際上雙精度數值的運算速度更快。
    所有超越數學函式,如sin()、cos()和 sqrt(),都返回雙精度值。如果需要在很多次迭代運算中保持精度,或是操作非常大的數值,double型別是最佳選擇。
	下面的簡短程式使用double變數計算圓的面積:





3.5字元型

	在Java中,用於儲存字元的資料型別是char。然而,C/C++程式設計師要當心:Java中的char與C或C++中的char是不同的。在C/C++中,char 的寬度是8位。
	而在Java中不是這樣的。相反,Java使用Unicode表示字元。Unicode定義了一個完全國際化的字符集,能夠表示全部人類語言中的所有字元。
	Unicode是數十種字符集的統一體,比如拉丁字符集、希臘字符集、阿拉伯字符集、斯拉夫語字符集、希伯來語字符集、日文字符集、韓文字符集等。
	為此,Unicode需要16位寬。因此,在Java中 char是16位型別。char的範圍為0~65 536。沒有負的char值。
	ASCII標準字符集的範圍仍然是0~127;而擴充套件的8位字符集 ISO-Latin-1,其範圍是0~255。
	既然Java 的設計初衷是允許程式設計師編寫在世界範圍內均可使用的程式,那麼使用Unicode表示字元是合理的。
	當然,對於英語、德語、西班牙語或法語這類語言,使用Unicode在一定程度上會降低效率,
	因為可以很容易地使用8位表示這類語言的字元。但這是為了在全球獲得可移植性而必須付出的代價。

	注意:
		在http//www.unicode.org上可以找到有關 Unicode的更多資訊







布林型別:

Java有一種稱為boolean的基本型別,用於表示邏輯值。
 它只能是兩個可能的值之一: true或false。
 所有關係運算(例如a<b)都返回這種型別的值。對於if和for這類控制語句的條件表示式,也需要boolean型別。





package com.alanliu.Java8BasicCodeStuding.Java8BasciCode.Unit3.Point7;
/**


3.7.1 整型字面值


	在典型的程式中,整型可能是最常用的型別。所有整數值都是整型字面值,例如1、2、3和42。這些都是十進位制數字,表示它們是以10為基數描述的。
	在整型字面值中,還可以使用另外兩種進位制——八進位制(以8為基數)和十六進位制(以16為基數)。
	在Java中,八進位制數值以О開頭。常規的十進位制數字不以О開頭。因此,對於看似有效的值09,編譯器會產生一個錯誤,因為9超出了八進位制數字0~7的範圍。
	程式設計師針對數字更常使用的是十六進位制,以便整齊地匹配以8為模的字的尺寸,如8位、16位、32位和64位。以0x或OX開頭來標識十六進位制常量。
	十六進位制數字的範圍是0~15,因此分別用A~F(或a~f)替代數字10~15。
	整型字面值用於建立int型別數值,在Java中是32位的整數。既然Java是強型別化的,您可能會好奇Java如何將整型字面值賦給其他整數型別,
	如 byte或long,而不會導致型別不匹配錯誤。幸運的是這種情況很容易處理。
	當將字面值賦給byte或short變數時,如果字面值位於目標型別的範圍之內,就不會產生錯誤。
	整型字面值總是可以賦給long變數。然而,為了標識long 字面值,需要明確告訴編譯器字面值是long型別的。
	可以通過為字面值附加一個大寫或小寫的L來明確地標識其型別為long,例如Ox7mmmL或9223372036854775807L是最大的long型別的字面值。
	也可以將整數賦給char,只要在char型別的範圍之內即可。

   從JDK 7開始,可以使用二進位制指定整型字面值。為此,使用0b或0B作為數值的字首。例如,下面這行程式碼使用二進位制字面值指定十進位制值10
   int x = 0b1010;

   除了其他用途之外,二進位制字面值簡化了用作位掩碼的數值的輸入。對於這種情況,十進位制(或十六進位制)表示的數值不能很直觀地表達出與其用途相關的含義,而二進位制字面值卻可以。
   從JDK 7開始,在整型字面值中還可以嵌入一個或多個下劃線。嵌入下劃線可以使閱讀很大的整數變得更加容易。當編譯字面值時,會丟棄下劃線。例如,下面這行程式碼:
   int x -123_456_789;
    為x提供的值為123 456789,下劃線將被忽略。下劃線只能用於分隔數字,不能位於字面值的開頭和結尾。然而,在兩個數字之間使用多個下劃線是允許的。例如,下面這行程式碼是合法的:
    int x = 123 _456_789; 當編碼電話號碼、消費者ID號、零件編碼等事物時,在整型字面值中使用下劃線特別有用。例如:二進位制數值經常以4位進行視覺分組。如下所示:
    int x= 0b1101_ 0101 。0001_ 1010;

3.7.2浮點型字面值
	浮點數表示具有小數部分的十進位制數值。可以使用標準計數法或科學計數法表示浮點數。
	標準計數法由前面的整數部分、其後的小數點以及小數點後面的小數部分構成。
	例如,2.0、3.14159 以及0.6667都表示有效的標準計數法浮點數。
	科學計數法使用-一個由標準計數法表示的浮點數加上一個字尾表示,其中的字尾指定為10的冪,它與前面的浮點數是相乘的關係。
	指數部分用E(或e)後面跟上一個十進位制數表示,該十進位制數可以是正數,也可以是負數,例如6.022E23、314159E-05 以及2e+100。

   在Java中,浮點型字面值預設是雙精度的。為了指定浮點型字面值,必須為常量附加一個F或f。也可以通過附加D或d來顯式地指定double字面值。當然,這麼做是多餘的。
   預設的double型別使用64位儲存,而更小的float型別只需要32位。

   Java也支援十六進位制浮點型字面量,但是很少使用。它們必須使用與科學計數法類似的形式來表示,不過使用的是P或p,而不是E或e.
   例如,0x12.2P2 是一一個有效的浮點型字面值。P後面的數值稱為二進位制指數,表示2的冪,並且和前面的數字相乘。所以,0x12.2P2代表72.5。

   從JDK 7開始,在浮點型字面值中可以嵌入- -個或多個下劃線。該特性和用於整型字面值時的工作方式相同,剛才已經介紹過。這- -特性的 目的是使閱讀很大的浮點型字面值更加容易。當編譯字面值時,會丟棄下劃線。
   例如,下面這行程式碼: double num = 9423_ 497_ 862.0;

   將變數num賦值為9423 497 862.0,下劃線會被忽略。與整型字面值一一樣,下劃線只能用於分隔數字。它們不能位於字面值的開頭或結尾。然而,在兩個數字之間使用多個下劃線是允許的。
   在小數部分中也可以使用下劃線,例如:double num=9_ 423_ 497.1_ 0_ 9;
   這是合法的。這時,小數部分是.109。

   3.7.3布 爾型字面值
    布林型字面值很簡單。布林型只有兩個邏輯值一-true 和false. true 和false 不能轉換成任何數字表示形式。在Java中,字面值true不等於1,字面值false也不等於0。
    在Java中,只能將布林型字面值賦給以布林型宣告的變數,或用於使用布林運算子的表示式中。
  3.7.4字元型字面值
   Java中的字元被索引到Unicode字符集,它們是可以轉換成整數的16位值,並且可以使用整數運算子進行操作,例如加和減運算子。
   字元型字面值使用位於一對單引號中的字元來表示。所有可見的ASCII字元都可以直接輸入到單引號中,如a、z以及'@'。
   對於那些不能直接輸入的字元,可以使用轉義字元序列輸入需要的字元,例如"表示單引號、"n'表示換行符。還有一-種以八進位制或十六進位制直接輸入字元值的機制。
   對於八進位制表示法,使用反斜槓後跟三位數字表示,例如141'是字母'a'。 對於十六進位制,先輸入“\ u”,然後是4位的十六進位制數。
   例如u0061表示ISO-Latin-1 字元a', 因為第- 個位元組為0; '\ua432是- -個JapanessKatakana字元。表3-3顯示了字元轉義序列。



   3.7.5字串字面值

   在Java中,指定字串字面值的方法與其他大多數語言相同一-使用位於一 對雙引號中的字元序列。下面是字串字面值的幾個例子:
   "Hello World"
   "two\nlines"
   ”\"This is in quotes\""
   為字元型字面值定義的轉義序列和八進位制/十六進位制表示法,在字串字面值中同樣適用。關於Java字串需要重點指出的是,它們的開頭和結尾必須位於同一行中。
   與其他某些語言不同,在Java中沒有續行的轉義序列。
   注意:
   您可能知道,在其他某些語言中,包括C/C++, 字串是作為字元陣列實現的。然而,在Java中不是如此。在Java中,字串實際上是物件型別。在本書的後面將會看到,
   因為Java將字串作為物件實現,所以提供了廣泛的、功能強大且易於使用的字串處理功能。


   3.8變數

 在Java程式中,變數是基本儲存單元。變數是通過聯合識別符號、型別以及可選的初始化器來定義的。此外,所有的變數都有作用域,作用域定義了變數的可見性和生存期。下面分析這些元素。

3.8.1變數的宣告
3.8.1變數的宣告
在Java中,所有變數在使用之前必須宣告。宣告變數的基本形式如下所示:
type identifier [- value ][, identifier [- value ]];
其中,type是Java的原子型別或是類或介面的名稱(類和介面型別將在本書第I部分的後面討論)。
identifier是變數的名稱。可以通過指定一個等號和一個值來初始化變數。
請牢記,初始化表示式的結果型別必須與為變數指定的型別相同(或相容)。
為了宣告指定型別的多個變數,需要使用以逗號分隔的列表。

下面是宣告各種型別變數的一些例子,注意有些變數宣告包含初始化部分:月計
	inta,b,C;     // declares three ints, a, b, and c.
	intd=3,e,f= 5;// declares three more ints. initializing
	               //dandf.
	bytez-22;       //initializes z.
	double pi =3.14159;// declares an approximation of pi.
	char x = 'x';      // the variable x has the value 'x'
在此選擇的識別符號與用來指定變數型別的名稱沒有任何內在聯絡。Java允許將任何形式的正確的識別符號宣告為任何型別。
Java允許將任何形式的正確識別符號宣告為任何型別


3.8.2動態初始化
儘管前面的例子只使用常量作為初始化器,但是在宣告變數時,Java也允許使用任何在宣告變數時有效的表示式動態地初始化變數。
例如,下面的簡短程式根據直角三角形的兩條直角邊來計算斜邊的長度:
// Demonstrate dynamic initialization.
class DynInit {
    public static void main(String args[]) {
      double a = 3.0, b = 4.0;

      // c is dynamically initialized
      double c = Math.sqrt(a * a + b * b);

      System.out.println("Hypotenuse is " + c);
    }
}
在此,聲明瞭三個區域性變數:a、b和c。其中的前兩個變數a和b,使用常量進行初始化,而C被動態初始化為斜邊的長度(使用勾股定理)。
該程式使用了另外-一個內建的Java方法sqrt(,該方法是Math類的成員,用於計算引數的平方根。
在此的關鍵點是,初始化表示式可以使用任何在初始化時有效的元素,包括方法呼叫、其他變數或字面值。


3.8.3變數的作用域和生存期
   到目前為止,使用的所有變數都是在main()方法開始時宣告的。然而,Java允許在任何程式碼塊中宣告變數。
正如在第2章中所解釋的,程式碼塊以開花括號開始並以閉花括號結束。程式碼塊定義了作用域。
因此,每當開始一個新的程式碼塊時就建立了一個新的作用域。作用域決定了物件對程式其他部分的可見性,並且也決定了這些物件的生存期。
   許多其他計算機語言定義了兩種通用的作用域類別:全域性作用域和區域性作用域。然而,這些傳統的作用域不能很好地適應Java中嚴格的、面向物件的模型。
雖然可以建立屬於全域性作用域的變數,但這只是例外,而不是規則。在Java中,兩種主要的作用域分別是由類和方法定義的。儘管這種分類有些人為因素,
但是,由於類作用域具有的一些獨特屬性和特性,不能應用於由方法定義的作用城,因此這種分類方法有一定的道理。
由於存在這種差別,對類作用域(以及在其中宣告的變數)的討論將推遲到第6章,那時會介紹類的相關內容。現在,只分析由方法定義以及在方法中定義的作用域。
    由方法定義的作用域從方法的開花括號開始。然而,如果方法具有引數,那麼它們也會被包含到方法的作用域中。
儘管本書在第6章會進一步分析引數,但是出於作用城討論的目的,在此將它們與任何其他方法變數一樣一併考慮。
   作為通用規則,在作用域中宣告的變數,對於在作用域之外定義的程式碼是不可見的(即不可訪問)。
因此,當在某個作用城中宣告變數時,就區域性化了該變數,並保護它免受未授權的訪問和/或修改。實際上,作用城規則為封裝提供了基礎。
   作用域是可以巢狀的。例如,每當建立一個程式碼塊時,就建立了一個新的、巢狀的作用域。
當遇到這種情況時,外層的作用域包圍了內層作用域。這意味著在外層作用域中宣告的物件對於內層作用域中的程式碼是可見的。
然而,反過來就不是這樣了,在內層作用城中宣告的物件,在內層作用域之外是不可見的。
為了理解巢狀作用城的影響,分析下面的程式:
 // Demonstrate block scope.
class Scope {
  public static void main(String args[]) {
    int x; // known to all code within main

    x = 10;
    if(x == 10) { // start new scope
      int y = 20; // known only to this block

      // x and y both known here.
      System.out.println("x and y: " + x + " " + y);
      x = y * 2;
    }
    // y = 100; // Error! y not known here

    // x is still known here.
    System.out.println("x is " + x);
  }
}


	正如註釋指出的,變數x是在main()作用城的開始處宣告的,因此main()方法中的所有後續程式碼都可以訪問變數x。
變數y是在if程式碼塊中宣告的,既然程式碼塊定義了作用域,所以只有對於if程式碼塊中的程式碼y才是可見的。
這就是為什麼在if程式碼塊之外,將“y=100;”註釋掉的原因。如果刪除前面的註釋符號,就會發生編譯時錯誤,
因為在if程式碼塊之外y不是可見的。在if程式碼塊的內部可以使用x,因為程式碼塊(即巢狀的作用域)中的程式碼可以訪問在外部作用域中宣告的變數。
	在程式碼塊中,可以在任意位置宣告變數,但是隻有在宣告之後變數才是有效的。
因此,如果在方法的開頭定義變數,那麼變數對於該方法的所有程式碼都是可見的。相反,如果在程式碼塊的末尾宣告變數,那麼變數是無用的,
因為沒有程式碼能夠訪問該變數。例如,下面的程式碼片段是無效的,因為count在宣告之前不能使用:
    // This fragnent is wrong!
   count = 100;// oops! cannot use count before it is declared!
   int count;
下面是另外一個重點,當進入變數的作用域時建立變數,當離開它們的作用域時銷燬變數。這意味著一旦離開作用域,變數就不會再保持原來的值。所以,對於在方法中宣告的變數來說,在兩次呼叫該方法之間,變數不會保持它們的值。此外,對於在程式碼塊中宣告的變數來說,當離開程式碼塊時會丟失它們的值。因此,變數的生存期被限制在作用域之內。
如果變數宣告包含初始化器,那麼每當進入宣告變數的程式碼塊時都會重新初始化變數。例如,分析下面的程式:
II Demonstrate lifetime of a variable
class LifeTlme {public static void main(string args[]){intxifor(x=0:x<C3:x++]{                         都式int y--1:11yisinitialized each time block is enteredsystem.out .printin("y is: -+ y: rl this always prints -1y=100;System.out.printlnl"y is now: "+ y)i容張組不出p阿
這個程式產生的輸出如下所示:
y1s:-1
y ia now:100
y1s:-1


下面是另外一個重點:當進入變數的作用域時建立變數,當離開它們的作用域時銷燬變數。
這意味著一旦離開作用域,變數就不會再保持原來的值。所以,對於在方法中宣告的變數來說,在兩次呼叫該方法之間,變數不會保持它們的值。
此外,對於在程式碼塊中宣告的變數來說,當離開程式碼塊時會丟失它們的值。因此,變數的生存期被限制在作用域之內。
如果變數宣告包含初始化器,那麼每當進入宣告變數的程式碼塊時都會重新初始化變數。例如,分析下面的程式:

// Demonstrate lifetime of a variable.
class LifeTime {
  public static void main(String args[]) {
    int x;

    for(x = 0; x < 3; x++) {
      int y = -1; // y is initialized each time block is entered
      System.out.println("y iz: " + y); // this always prints -1
      y = 100;
      System.out.println("y is now: " + y);
    }
  }
}
這個程式產生的輸出如下所示:
法1總副..2.6
yis:-1
yis now:100
y1s:-1
可以看出,每次進入內部的for迴圈時y都被重新初始化為-1。儘管隨後y被賦值為100,但是這個值丟失了。
最後一點:儘管可以巢狀程式碼塊,但是在內層程式碼塊中不能宣告與外層程式碼塊具有相同名稱的變數。例如,下面的程式是非法的:
// This program will not compile
class ScopeErr {
   public static void main(String args[]) {
     int bar = 1;
     {              // creates a new scope
       int bar = 2; // Compile time error -- bar already defined!
     }
   }
}



3.9型別轉換和強制型別轉換
	如果您已經具備了程式設計經驗,就會知道將某種型別的值賦給另外一種型別的變數是很常見的。如果這兩種型別是相容的,那麼Java會自動進行型別轉換。
	例如,總是可以將int型別的值賦給long型別的變數。然而,並不是所有型別都是相容的,從而也不是所有型別轉換預設都是允許的。
	例如,沒有定義從double型別到byte型別的自動轉換。幸運的是,在兩種不相容的型別之間,仍然可以進行轉換。
	為此,必須使用強制型別轉換(cast),在不相容的型別之間執行顯式轉換。下面分析自動型別轉換和強制型別轉換這兩種情況。
3.9.1Java的自動型別轉換
	當將某種型別的資料賦給另外一種型別的變數時,如果滿足如下兩個條件,就會發生自動型別轉換:
  ●兩種型別是相容的。
  ●目標型別大於源型別。
	當滿足這兩個條件時,會發生擴寬轉換(widening conversion)。例如,要儲存所有有效的byte值,int型別總是足夠的,所以不需要顯式的強制轉換語句。
  對於擴寬轉換,數值型別(包括整型和浮點型)是相互相容的。然而,不存在從數值型別到char或boolean型別的自動轉換。此外,char和boolean相互之間也不是相容的。
  在前面提到過,當將字面整數常量儲存到byte、short. long或char型別的變數中時,Java也會執行自動型別轉換。

3.9.2強制轉換不相容的型別
	儘管自動型別轉換很有幫助,但是它們不能完全滿足全部需要。例如,如果希望將int型別的值賦給byte變數,會發生什麼情況呢?
 不會自動執行轉換,因為byte比int更小。這種轉換有時被稱為縮小轉換(narrowing conversion),因為是顯式地使數值變得更小以適應目標型別。
 為了實現兩種不相容型別之間的轉換,必須使用強制型別轉換。強制型別轉換隻不過是一種顯式型別轉換,它的一般形式如下所示:
 (target-type) value
 其中,target-type指定了期望將特定值轉換成哪種型別。
 例如,下面的程式碼片段將int型別的值強制轉換為byte型別。
 如果整數的值超出了byte型別的範圍,結果將以byte型別的範圍為模(用整數除以byte範圍後的餘數)減少。
  int a;
  byte b; //i -
  b=(byte) a;
	當將浮點值賦給整數型別時會發生另一種不同型別的轉換:截尾(runcation)。
  您知道,整數沒有小數部分。因此,當將浮點值賦給整數型別時,小數部分會丟失。
  例如,如果將數值1.23賦給一個整數,結果值為1,0.23將被截去。當然,如果整數部分的數值太大,以至於無法儲存到目標整數型別中,那麼數值將以目標型別的範圍為模減少。
	下面的程式演示了一些需要進行強制型別轉換的轉換:
// Demonstrate casts.
class Conversion {
  public static void main(String args[]) {
    byte b;
    int i = 257;
    double d = 323.142;

    System.out.println("\nConversion of int to byte.");
    b = (byte) i;
    System.out.println("i and b " + i + " " + b);

    System.out.println("\nConversion of double to int.");
    i = (int) d;
    System.out.println("d and i " + d + " " + i);

    System.out.println("\nConversion of double to byte.");
    b = (byte) d;
    System.out.println("d and b " + d + " " + b);
  }
}
這個程式產生的輸出如下所示:

Conversion of int to byte.
i and b 257 1

Conversion of double to int.
d and i 323.142 323

Conversion of double to byte.
d and b 323.142 67

下面對每個轉換進行分析。
		當數值257被強制轉換為byte變數時,結果是257除以256(byte型別的範圍)的餘數,也就是1。
		當將d轉換成int型別時,小數部分丟失了。
		當將d轉換成byte型別時,小數部分也丟失了,並且值以256為模減少,結果為67。

/**

3.10表示式中的自動型別提升
	除了賦值外,還有另外一個地方也可能會發生某些型別轉換:在表示式中。為了分析其中的原因,考慮下面的情況。
在表示式中,中間值要求的精度有時會超出運算元的範圍。例如,檢查下面的表示式:
是學是的學
  byte a=40;
  byte b=50;
  byte c=100;
  int d=a*b/c;

	中間部分a*b的結果很容易超出byte運算元的範圍。為了解決這類問題,當對錶達式求值時,Java自動將每個byte、short或char運算元提升為int型別。
這意味著使用int型別而不是byte型別執行子表示式a*b。因此,儘管a和b都被指定為byte型別,中間表示式(50*40)的結果2000是合法的。
	儘管自動型別提升很有用,但是它們會導致難以理解的編譯時錯誤。例如,下面的程式碼看起來是正確的,但是會導致問題:
   byte b=50;
   b= b*2:// Error! Cannot assign an int to a byte!
	上面的程式碼試圖將50*2個完全有效的byte值一一儲存在一個byte變數中。但是,當計算表示式的值時,運算元被自動提升為int型別,
所以結果也被提升為int型別。因此,現在表示式的結果是int型別,如果不使用強制型別轉換,就不能將結果賦給那個byte變數。
儘管對於這個特定情況來說,所賦予的值仍然滿足目標型別,但是仍然需要進行強制型別轉換。
	如果能理解溢位產生的後果,就應當使用顯式的強制型別轉換,如下所示:
	byte b =50;
	 b=(byte)(b*2);
	這樣就可以得到正確的值100。






型別提升規則
	Java定義了幾個應用於表示式的型別提升規則,如下所示:首先,正如剛才所描述的,所有byte. short和char型別的值都被提升為int型別。
然後,如果有一個運算元是long型別,就將整個表示式提升為long型別;
如果有一個運算元是float型別,就將整個表示式提升為float型別;
如果任何一個運算元為double型別,結果將為double型別。
下面的程式演示了為了使第二個引數與每個二元運算子相匹配,如何提升表示式中的每個值:
 class Promote {
  public static void main(String args[]) {
    byte b = 42;
    char c = 'a';
    short s = 1024;
    int i = 50000;
    float f = 5.67f;
    double d = .1234;
    double result = (f * b) + (i / c) - (d * s);
    System.out.println((f * b) + " + " + (i / c) + " - " + (d * s));
    System.out.println("result = " + result);
  }
}
 下面進一步分析程式中如下這行程式碼中的型別提升:
double result = (f *b) +(i/c)-(d*s);
在第一個子表示式f*b中,b被提升為float型別,並且該子表示式的結果也是float型別。
接下來在子表示式ic中,c被提升為int型別,並且結果也是int型別。
然後在d*s中,s的值被提升為double型別,並且該子表示式的型別為double。
最後考慮三個中間值的型別float、 int和double。
float加上int的結果是float。之後,作為結果的float減去最後的double,會被提升為double,這就是表示式最終結果的型別。







**/
為人:謙遜、激情、博學、審問、慎思、明辨、 篤行
學問:紙上得來終覺淺,絕知此事要躬行
為事:工欲善其事,必先利其器。
態度:道阻且長,行則將至;行而不輟,未來可期
轉載請標註出處!