1. 程式人生 > >第3章 Java的基本程式設計結構

第3章 Java的基本程式設計結構

1、下面是用於表示溢位和出錯情況的三個特殊的浮點數值 :
• 正無窮大
• 負無窮大
• NaN
( 不是一個數字 )
例如 , 一 正整數除以 0 的結果為正無窮大 。 計算 0 / 0 或者負數的平方根結果為 NaN 。

2、常量 Double _ POSITIVE _ INFINITY 、 Double . NEGATIVEJNFINITY 和 Double . NaN
( 以及相應的 Float 型別的常量 ) 分別表示這三個特殊的值,但在實際應用中很少遇到 。
特別要說明的是 , 不能這樣檢測一個特定值是否等於 Double . NaN :
if ( x = Double . NaN ) / / is never true
所有 “ 非數值 ” 的值都認為是不相同的 。


然而 , 可以使用 Double . isNaN 方法 :
if ( Double . isNaN ( x ) ) / / check whether x is " not a number "

3、警告 : 浮點數值不適用於無法接受舍入誤差的金融計算中 。 例如 , 命令 System . out . println( 2.0 - 1.1 ) 將打印出 0.8999999999999999 , 而不是人們想象的 0.9
。 這種舍入誤差的主要原因是浮點數值採用二進位制系統表示 , 而在二進位制系統中無法精確地表示分數 1 / 10。 這就好像十進位制無法精確地表示分數 1 / 3—樣。 如果在數值計算中不允許有任何舍入誤差 ,就應該使用 BigDecimal類 。

4、char 型別的值可以表示為十六進位制值, 其範圍從 \ u 0000 到 \ Uffff。

5、 C++註釋:在 C + + 中 , 數值甚至指標可以代替 boolean 值。 值 0 相當於布林值 false ,非0 值相當於布林值 true , 在 Java 中則不是這樣 , 因此, Java 程式設計師不會遇到下述麻煩 :
if ( x = 0 ) / / oops . … meant x = 0
在 C + + 中這個測試可以編譯執行,其結果總是 false : 而在 Java 中 , 這個測試將不
能通過編譯, 其原因是整數表示式 x = 0 不能轉換為布林值 。

6、 強制型別轉換的語法格式是在圓括號中給出想要轉換的目標型別 , 後面緊跟待轉換的變數名 。 例如 :
double x * 9.997 ;
int nx = ( int ) x ;
這樣 , 變數 nx 的值為 9。 強制型別轉換通過截斷小數部分將浮點值轉換為整型 。
如果想對浮點數進行舍人運算 , 以便得到最接近的整數 ( 在很多情況下 , 這種操作更有用 ), 那就需要使用 Math.round
方法 :
double x z 9.997 ;
int nx = ( int ) Math . round ( x ) ;
現在 , 變數 nx 的值為 10。
當呼叫 round 的時候 , 仍然需要使用強制型別轉換 ( int ) 。 其原因
是 round 方法返回的結果為 long 型別 , 由於存在資訊丟失的可能性 , 所以只有使用顯式的強制型別轉換才能夠將 long 型別轉換成 int 型別 。

7、另外, 還有 >>和 << 運算子將位模式左移或右移 。 需要建立位模式來完成位掩碼時
, 這兩個運算子會很方便 :
int fourthBitFromRight = ( n & ( 1 « 3 ) ) » 3 ;
最後,>>> 運算子會用 0 填充高位, 這與 》不同, 它會用符號位填充高位 。 不存在
<<<運算子。

8、字串專題:
(1)、子串提取:
String 類的 substring 方法可以從一個較大的字串提取出一個子串 。 例如 :
String greeting = " Hello " ;
String s = greeting . substring ® , 3 ) ;
建立了一個由字元 “ Hel ” 組成的字串 。substring 方法的第二個引數是不想複製的第一個位置 。 這裡要複製位置為 0、 1和 2 ( 從0 到 2 , 包括 0 和 2 ) 的字元。 在 substring 中從 0 開始計數 , 直到 3 為止 , 但不包含 3 。
substring 的工作方式有一個優點 : 容易計運算元串的長度 。 字串 s . substring ( a , b ) 的長度為 b - a。 例如 , 子串 “Hel ” 的長度為 3 - 0 = 3。
(2)、判等:一定不要使用 = 運算子檢測兩個字串是否相等 ! 這個運算子只能夠確定兩個字串
是否放置在同一個位置上 。 當然 , 如果字串放置在同一個位置上 , 它們必然相等
。 但是 ,
完全有可能將內容相同的多個字串的拷貝放置在不同的位置上

可以使用 equals 方法檢測兩個字串是否相等 。 對於表示式 :
s . equal s ( t )
如果字串 s 與字串 t 相等 , 則返回 true ; 否則 , 返回 false。 需要注意 , s 與 t
可以是字串變數 , 也可以是字串字面量 。 例如 , 下列表達式是合法的 :
" Hello " . equals ( greeting )
要想檢測兩個字串是否相等, 而不區分大小寫 , 可以使用 equalsIgnoreCase
方法。
" Hello " . equalsIgnoreCase ( " hello " )
(3)、空串與NULL
空串 " " 是長度為 0 的字串。 可以呼叫以下程式碼檢查一個字串是否為空:
if ( str . lengthQ = 0 )

if ( str . equals ( “” ) )
空串是一個 Java 物件 , 有自己的串長度 ( 0 ) 和內容 ( 空 )。 不過 , String變數還可以存放一個特殊的值 , 名為 null , 這表示目前沒有任何物件與該變數關聯 。要檢查一個字串是否為 null , 要使用以下條件 :
if ( str = = null )
有時要檢查一個字串既不是 null 也不為空串, 這種情況下就需要使用以下條件 :
if ( str ! = null & & str . lengthO ! = 0 )
首先要檢查 str 不為 null。 如果在一個 mull 值上呼叫方法 , 會出現錯誤。
(4)、字串的遍歷及碼點與程式碼單元
Java 字串由 char 值序列組成。 從3.3 . 3 節 “ char 型別 ” 已經看到 , char 資料型別是一個採用 UTF - 16 編碼表示 Unicode 碼點的程式碼單元。 大多數的常用 Unicode 字元使用一個程式碼單元就可以表示 , 而輔助字元需要一對程式碼單元表示。length 方法將返回採用 UTF - 16 編碼表示的給定字串所需要的程式碼單元數量 。 例如 :
String greeting = " Hello " ;
int n = greeting . length 。 ; / / is 5 .
要想得到實際的長度, 即碼點數量 , 可以呼叫 :
int cpCount = greeting . codePointCount ( 0 , greeting . lengthQ ) ;
呼叫 s . charAt ( n ) 將返回位置 n 的程式碼單元, n介於 0 ~ s . length ( ) - l 之間。 例如 :
char first = greeting . charAtO ) ;//first is ’ H ’
char last = greeting . charAt ( 4 ) ; / / last is ’ o ’
要想得到第 i 個碼點, 應該使用下列語句
int index = greeting . offsetByCodePoints ( 0 , i ) ;
int cp = greeting . codePointAt ( index ) ;
(5)、java String API
API java . lang . string 1.0

  • char charAt ( int index )
    返回給定位置的程式碼單元。 除非對底層的程式碼單元感興趣 ,否則不需要呼叫這個方法。
  • intcodePointAt ( int Index ) 5.0
    返回從給定位置開始的碼點。
  • int offsetByCodePoints ( int startlndex , int cpCount ) 5.0
    返回從 startlndex 程式碼點開始, 位移 cpCount 後的碼點索引 。
  • int compareTo ( String other )
    按照字典順序, 如果字串位於 other 之前 , 返回一個負數 ; 如果字串位於other 之後, 返回一個正數 ; 如果兩個字串相等 , 返回0。
  • IntStream codePoints ( ) 8
    將這個字串的碼點作為一個流返回。 呼叫 toArray 將它們放在一個數組中 。
  • new String ( int [ ] codePoints , int offset , int count ) 5.0
    用陣列中從 offset 開始的 count 個碼點構造一個字串。
  • boolean equals ( 0 bject other )
    如果字串與 other 相等 , 返回 true。
  • boolean equalsIgnoreCase ( String other )
    如果字串與 other 相等 ( 忽略大小寫 ), 返回 true 。
  • boolean startsWith ( String prefix )
  • boolean endsWith ( String suffix )
    如果字串以 suffix 開頭或結尾 , 則返回 true。
  • int indexOf ( String str )
  • int indexOf ( String str , int fromlndex )
  • int indexOf ( int cp )
  • int indexOf ( int cp , int fromlndex )
    返回與字串 str 或程式碼點 cp 匹配的第一個子串的開始位置。 這個位置從索引0 或fromlndex 開始計算 。 如果在原始串中不存在 str , 返回 - 1。
  • int lastIndexOf ( String str )
  • Int lastIndexOf ( Stri ng str , int fromlndex )
  • int lastindexOf ( int cp )
  • int lastindexOf ( int cp , int fromlndex )
    返回與字串 str 或程式碼點 cp 匹配的最後一個子串的開始位置 。 這個位置從原始串尾端或 fromlndex 開始計算。
  • int length ( )
    返回字串的長度 。
  • int codePointCount ( int startlndex , int endlndex ) 5.0
    返回 startlndex 和 endludex - l 之間的程式碼點數量。 沒有配成對的代用字元將計入程式碼點 。
  • String replace ( CharSequence oldString , CharSequence newString )
    返回一個新字串。 這個字串用 newString代替原始字串中所有的 oldString
    。 可以用 String 或 StringBuilder 物件作為 CharSequence 引數 。
  • String substring ( int beginlndex )
  • String substring ( int beginlndex , int endlndex )
    返回一個新字串。 這個字串包含原始字串中從beginlndex 到串尾或 endlndex - 1的所有程式碼單元。
  • String toLowerCase ( )
  • String toUpperCase ( )
    返回一個新字串 。 這個字串將原始字串中的大寫字母改為小寫 , 或者將原始字串中的所有小寫字母改成了大寫字母。
  • String trim( )
    返回一個新字串。 這個字串將刪除了原始字串頭部和尾部的空格 。
  • String join ( CharSequence delimiter , CharSequence . … elements ) 8
    返回一個新字串 , 用給定的定界符連線所有元素 。
    (6)、構建字串:
    有些時候 , 需要由較短的字串構建字串 , 例如 , 按鍵或來自檔案中的單詞。 採用字串連線的方式達到此目的效率比較低。 每次連線字串 ,都會構建一個新的 String 物件 ,既耗時 , 又浪費空間。 使用StringBuildei 類就可以避免這個問題的發生。
    如果需要用許多小段的字串構建一個字串 , 那麼應該按照下列步驟進行 。 首先 , 構建一個空的字串構建器 :
    StringBuilder builder = new StringBuilderO ;
    當每次需要新增一部分內容時 , 就呼叫 append 方法 。
    builder . append ( ch ) ; / / appends a single character
    bui 1 der . append ( str ) ; / / appends a string
    在需要構建字串時就凋用 toString 方法 , 將可以得到一個 String 物件 , 其中包含了構建器中的字元序列 。
    String completedString = builder . toStringO ;
    註釋 : 在 JDK 5.0 中引入 StringBuilder 類 。 這個類的前身是 StringBuffer ,
    其效率稍有些低,但允許採用多執行緒的方式執行新增或刪除字元的操作 U 如果所有字串在一個單執行緒中編輯 ( 通常都是這樣 ),則應該用 StringBuilder 替代它 。 這兩個類的 AP 丨是相同的 。
    (7)重中之重的java StringBuilder API(可以直接對其增刪改)
    •StringBuilder ()
    構造一個空的字串構建器。
    •int length ( )
    返回構建器或緩衝器中的程式碼單元數量。
    • StringBuilder appencl ( Stri ng str )
    追加一個字串並返回 this。
    •StringBuilder append ( char c )
    追加一個程式碼單元並返回 this。
    •StringBuilder appendCodePoint ( int cp )
    追加一個程式碼點, 並將其轉換為一個或兩個程式碼單元並返回 this 。
    •void setCharAt ( int i , char c )
    將第 i 個程式碼單元設定為 c。
    •StringBuilder insert ( int offset , String str )
    在 offset 位置插入一個字串並返回 this。
    • StringBuilder insert ( int offset , Char c )
    在 offset 位置插入一個程式碼單元並返回 this。
    •StringBuilder delete ( int startindex , int endlndex )
    刪除偏移量從 startindex 到 - endlndex - 1 的程式碼單元並返回 this。
    •String toString ( )
    返回一個與構建器或緩衝器內容相同的字串

9、標準流輸入(關於緩衝區回車問題稍後再研究):
API java . util . Scanner 5.0

•Scanner ( InputStream in )
用給定的輸人流建立一個 Scanner 物件。
•String nextLine ( )
讀取輸入的下一行內容。
•String next ( )
讀取輸入的下一個單詞 ( 以空格作為分隔符 )。
•int nextlnt ( )
•double nextDouble ( )
讀取並轉換下一個表示整數或浮點數的字元序列 。
•boolean hasNext ( )
檢測輸人中是否還有其他單詞。
•boolean hasNextInt ( )
•boolean hasNextDouble ( )
檢測是否還有表示整數或浮點數的下一個字元序列 。

10.格式化輸出(關於格式化輸出與字串高階處理部分,部分此書講的並不足夠詳細,稍後自己擴充套件。):
(1)、非常慶幸java SE5.0以後沿用了C語言的printf()格式化控制輸出手段。
(2)、可以使用 s 轉換符格式化任意的物件 , , 對於任意實現了 Formattable 介面的物件都將呼叫 formatTo 方法 ; 否則將呼叫 toString 方法 , 它可以將物件轉換為字串 。

11、java時間類與檔案暫時先略。

12、高精度福音,java大數值類:
(1)、 那麼可以使用 java . math 包中的兩個很有用的類 : Biglnteger 和 BigDecimaL 這兩個類可以處理包含任意長度數字序列的數值。Biglnteger 類實現了任意精度的整數運算 , BigDecimal 實現了任意精度的浮點數運算 。
(2)、使用靜態的 valueOf 方法可以將普通的數值轉換為大數值 :
Biglnteger a = Biglnteger . valueOf ( 100 )
(3)、遺憾的是, 不能使用人們熟悉的算術運算子 ( 如 : + 和 *) 處理大數值。
而需要使用大數值類中的 add 和 multiply 方法 。
Biglnteger c = a . add ( b ) ; / / c = a + b
Biglnteger d = c . nultipiy ( b . add ( Biglnteger . valueOf ( 2 ) ) ) ; // d = c * ( b + 2 )
(4)、java 大數值類API:
API java . math . Biglnteger 1.1
•Biglnteger add ( Biglnteger other )
•Biglnteger subtract ( Biglnteger other )
•Biglnteger multipiy ( Biginteger other )
•Biglnteger divide ( Biglnteger other )
•Biglnteger mod ( Biglnteger other )
返冋這個大整數和另一個大整數 other的和、 差 、積 、 商以及餘數 。
•int compareTo ( Biglnteger other )
如果這個大整數與另一個大整數 other 相等 , 返回 0 ; 如果這個大整數小於另一個大整數 other , 返回負數 ; 否則 , 返回正數 。
•static Biglnteger valueOf ( long x )
返回值等於 x 的大整數 。

API java . math . BigDecimal 1.1
•BigDecimal add ( BigDecimal other )
•BigDecimal subtract ( BigDecimal other )
•BigDecimal multipiy ( BigDecimal other )
•BigDecimal divide ( BigDecimal other RoundingMode mode ) 5.0
返回這個大實數與另一個大實數 other 的和 、 差 、 積 、 商。 要想計算商 ,
必須給出舍入方式 ( rounding mode )。 RoundingMode . HALF_UP 是在學校中學習的四捨五入方式( 即 , 數值 0 到 4 捨去, 數值5 到 9 進位 )。 它適用於常規的計算 。 有關其他的舍入方式請參看 ApI 文件。
•int compareTo ( BigDecimal other )
如果這個大實數與另一個大實數相等 , 返回 0 ; 如果這個大實數小於另一個大實數 ,
返回負數 ; 否則, 返回正數 。
•static BigDecimal valueOf ( long x )
•static BigDecimal valueOf ( long x , int scale )
返回值為 X 或 x / 10 scale 的一個大實數 。

13、陣列:
(1)、程式碼風格:可以使用下面兩種形式宣告陣列
int [] a ;

int a [] ;
大多數 Java 應用程式設計師喜歡使用第一種風格
,因為它將型別 int [] ( 整型陣列 ) 與變數名分開了 。
(2)、陣列初始化:建立一個數字陣列時 , 所有元素都初始化為 0。 boolean 陣列的元素會初始化為false, 物件陣列的元素則初始化為一個特殊值 null , 這表示這些元素還未存放任何物件。 初學者對此可能有些不解。 例如 ,
String [ ] names = new String [ 10 ] ;
會建立一個包含 10 個字串的陣列 , 所有字串都為 null。 如果希望這個陣列包含空串 , 可以為元素指定空串 :
for ( int i = 0 ; i < 10 ; i + + ) names [ i ] = “”;
(3)、for each迴圈:
for ( int element : a )
System . out . println ( element ) :
列印陣列 a 的每一個元素 , 一個元素佔一行。
(4)、陣列拷貝:
在 Java 中, 允許將一個數組變數拷貝給另一個數組變數。 這時 ,兩個變數將引用同一 個數組 :
int[ ] luckyNumbers = small Primes ;
luckyNumbers [ S ] = 12 ; // now small Primes [ 5 ] is also 12
如果希望將一個數組的所有值拷貝到一個新的陣列中去 ,就要使用 Arrays 類的 copyOf 方法 :
int [ ] copiedLuckyNumbers = Arrays . copyOf ( luckyNumbers , luckyNumbers . length ) ;
第 2 個引數是新陣列的長度 。 這個方法通常用來增加陣列的大小 :
luckyNumbers = Arrays . copyOf ( luckyNumbers , 2 * luckyNumbers . length ) ;
如果陣列元素是數值型, 那麼多餘的元素將被賦值為 0 ;
如果陣列元素是布林型, 則將賦值為 false。 相反 , 如果長度小於原始陣列的長度 , 則只拷貝最前面的資料元素 。
(5)、陣列排序:
要想對數值型陣列進行排序 , 可以使用 Arrays 類中的 sort 方法 :
int [] a = new int [ 10000 ] ;
Arrays . sort ( a )
這個方法使用了優化的快速排序演算法。
(6)、重中之中的陣列API
•static String toString ( type [] a ) 5.0
返回包含 a 中資料元素的字串 , 這些資料元素被放在括號內 , 並用逗號分隔 。
引數 : a 型別為 int 、 long、 short 、 char 、 byte 、 boolean 、 float或 double 的陣列。
•static type copyOf ( type [] a , int length ) 6
• static type copyOfRange ( type [] a , int start , int end ) 6
返回與 a 型別相同的一個數組 , 其長度為 length 或者 end - start , 陣列元素為 a 的值。
引數 :
a 型別為 int 、 long 、 short 、 char 、 byte、 boolean 、 float或 double 的陣列。
start 起始下標 ( 包含這個值 )。
end 終止下標 ( 不包含這個值 )。 這個值可能大於a . length。 在這種情況下 , 結果為 0 或 false。
length 拷貝的資料元素長度 c 如果 length 值大於 a . length , 結果為 0 或 false ;否則 ,陣列中只有前面 length 個數據元素的拷貝值。
• static void sort ( type [ 2 a )
採用優化的快速排序演算法對陣列進行排序 。
引數 : a 型別為 int 、 long 、 short 、 char 、 byte 、 boolean、 float或 double 的陣列。
• static int binarySearch ( type [ ] a , type v )
•static int binarySearch ( type [ ] a , int start , int end , type v ) 6
採用二分搜尋演算法查詢值 v。 如果查詢成功 ,則返回相應的下標值 ; 否則 , 返回一個
負數值 r。 - r - 1是為保持 a 有序 v 應插入的位置。
引數 :
a 型別為 int 、 long 、 short 、 char 、 byte 、 boolean 、 float 或 double 的有序陣列。
start 起始下標 ( 包含這個值 )。
end 終止下標 ( 不包含這個值 )。
v 同 a 的資料元素型別相同的值。
•static void fi 11 ( type [] a , type v )
將陣列的所有資料元素值設定為 V。
引數 :
a 型別為 int 、 long 、 short 、 char 、 byte 、 boolean 、 float 或 double 的陣列。
v 與 a 資料元素型別相同的一個值。
•static boolean equals ( type [] a , type [] b )
如果兩個陣列大小相同 , 並且下標相同的元素都對應相等 , 返回 true。
引數 :
a 、 b 型別為 int 、 long 、 short 、 char 、 byte 、 boolean 、 float 或 double 的兩個陣列 。

14、java隨機數生成:
Math . rand 0 m 方法將返回一個0 到 1 之間 ( 包含 0、不包含 1 ) 的隨機浮點數。 用
乘以這個浮點數 , 就可以得到從 0 到 n - l 之間的一個隨機數。
int r = ( int ) ( Math . random 0 * n ) ;

15、java多維陣列本質“陣列的陣列”:
Java 實際上沒有多維陣列, 只有一維陣列 。 多維陣列被解釋為 “ 陣列的陣列 。
balances = new double [ NYEARS ][ NRATES ] :
表示式 balancesf[ i ] 引用第 i 個子陣列, 也就是二維表的第i 行 。 它本身也是一個數組 ,
balances [ i ] [ j ] 引用這個陣列的第 j 項 。
由於可以單獨地存取陣列的某一行 , 所以可以讓兩行交換。
doubleQ temp = balances [ i ] :
balances [ i ] = balances [ i + 1 ] ;
balances [ i + 1 ] = temp ;

16、C + + 註釋 :
在 C + + 中 , Java 宣告
doublet [ ][ ] balances = new double [ 10 ] [ 6 ] ; // 3 ava
不同於
double balances [ 10 ] [ 6 ] ; / / C + +
也不同於
double ( * balances ) [ 6 ] = new double [ 10 ] [ 6 ] ; / / C + +
而是分配了一個包含 10 個指標的陣列 :
double * * balances = new double * [ 10 ] ; // C + +
然後 , 指標陣列的每一個元素被填充了一個包含 6 個數字的陣列 :
for ( i = 0 ; i < 10 ; i + + )
balances [ i ] = new double [ 6 ] ;
慶幸的是 , 當建立 new double [ 10 ][ 6 ] 時 , 這個迴圈將自動地執行 。
當需要不規則的陣列時 , 只能單獨地建立行陣列 。