第一章 Java程序設計概述java
在網頁中運行的Java程序稱爲 applet.express
在服務器中運行的Java程序稱爲 servlet.數組
關於Java的常見誤解:服務器
其中第三點說到: 3.Java是一種很是容易學習的程序設計語言app
像Java這種功能強大的語言大都不太容易學習. 首先,必須將編寫玩具式程序的輕鬆和開發實際項目的艱難區分開來.函數
第二章 Java程序設計環境學習
Windows 或 Linux : 32位選擇x86, 64位以 x64測試
第三章 Java的基本程序設計結構this
3.1 一個簡單的Java應用程序編碼
根據Java語言規範, main方法必須聲明爲pulic, 不過, 當main方法不是public時, 有些版本的Java解釋器也能夠執行Java程序.
在Java SE 1.4 及之後的版本中,強制main方法時public的.
3.2 註釋
在Java中,有三種標記註釋的方式。最經常使用的方式是使用 // ,其註釋內容從 // 開始到本行結束
System.out.println(" We will not use 'Hello World!'"); // is this too cute?
當須要長篇的註釋時時,既能夠在每行註釋前標記//,也可使用/* 和 */ 將一段比較長的註釋括起來。
第三種註釋能夠用來自動生成文檔,這種文檔以/** 開始,以*/ 結束。
/** * This is the first sample program in Core Java Chapter 3 * @param args */ public static void main(String[] args) { System.out.println(" We will not use 'Hello World!'"); // is this too cute? }
在Java中, /* */ 註釋不能嵌套。也就是說,不能簡單地把代碼用/* 和 */括起來做爲註釋,由於這段代碼自己可能也含一個 */ 。
3.3 數據類型
Java是一種強類型語言. 這就意味着必須爲每個變量聲明一種類型.
在Java中,一共有8種基本類型(primitive type)
3.3.1 整型
其中有4種整型、2種浮點類型、1種用於表示Unicode編碼的字符單元的字符類型 char 和 1 種用於表示真值的boolean 類型。
類型 | 存儲需求 | 取值範圍 |
int |
4字節 | -2 147 483 648 ~ 2 147 483 647 (正好超過21億) |
short |
2字節 | -32 768 ~ 32767 |
long |
8字節 | -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807 |
byte |
1字節 | -128 ~ 127 |
在一般狀況下,int類型最經常使用。但若是表示星球上的居住人數,就須要使用long類型了。byte 和 short 類型主要用於特定的應用場合,例如,底層的文件處理或者須要控制佔用空間量的大數組。
3.3.2 浮點類型
浮點類型用於表示有小數部分的數值。在Java中有兩種浮點類型
類型 | 存儲需求 | 取值範圍 |
float | 4字節 | 大約 +- 3.402 823 47E+38F(有效位數爲6~7位) |
double | 8字節 | 大約 +- 1.797 693 134 862 315 72E+308(有效位數爲15位) |
可使用十六進制表示浮點數值。例如,0.125=2-3 能夠表示成0x1.0p-3
在十六進制表示法中,使用p表示指數,而不是e。注意,尾數採用十六進制,指數採用十進制。指數的基數是2,而不是10。
用於表示溢出或出錯狀況的三個特殊的浮點數值:
例如:一個正整數除以0的結果爲正無窮大。計算0/0或者負數的平方根結果爲NaN。
特別要說明的是,不能這樣檢測一個特定值是否等於Double.NaN:
double x = 0.2; if (x == Double.NaN){ // is never true System.out.println("x == Double.NaN"); }全部「非數值」的值都認爲i是不相同的。然鵝,可使用Double.isNaN方法:
if (Double.isNaN(x))// check whether x is "not a number"浮點數不適用於沒法接受舍入偏差的金融計算中。例如:
System.out.println(2.0-1.1); // 輸出結果爲:0.8999999999999999而不是凡人們想象的 0.9 。
這種舍入偏差的主要緣由是浮點數值採用二進制系統表示,而在二進制系統中沒法精確地表示分數1/10 。
這就好像十進制沒法精確地表示分數1/3 同樣。
若是在數值計算中不容許有任何舍入偏差,就應該使用BigDecimal類。
3.3.3 char類型
char類型的字面量值要用單引號括起來。例如'A' 是編碼值爲65所對應的字符常量。它與"A" 不一樣,"A"是包含一個字符A的字符串。char類型的值能夠表示爲十六進制,其範圍從 \u0000 到 \Uffff 。例如:
\u2122 表示註冊符號(™),\u03C0 表示希臘字母π。
3.3.4 Unicode與char類型
3.3.5 boolean類型
boolean(布爾)類型有兩個值:false和true,用來判斷邏輯條件。整型值和布爾值之間不能進行相互轉換。
3.4 變量
3.4.1 變量初始化
3.4.2 常量
在Java中,可使用關鍵字static final 設置一個常量類。須要注意的是,常量類定義位於main方法地外部。
3.5 運算符
須要注意:整數被0除將會產生一個異常,而浮點數被0除將會獲得無窮大或NaN結果。
3.5.1 數學函數與常量
在Java中,沒有冪運算,須要藉助Math類得pow方法。語句:
double x = 2; double a = 3; double y = Math.pow(x,a); System.out.println(y); // 輸出 8.0
3.5.2 數值類型之間的轉換
上圖中6個實心箭頭,表示無信息丟失的轉換;有3個虛箭頭,表示可能有精度損失地轉換。例如:123456789 是一個大整數,它所包含的位數比float類型所可以表達的位數大,當將這個整數數值轉換爲float類型時,將會獲得一樣大小的結果,但卻失去了必定的精度。
int n = 123456789; float f = n; // f is 1.23456792E8
當使用上面的兩個數值進行二元操做時,先將兩個操做數轉換爲同一種類型,而後再進行計算。
3.5.3 強制類型轉換
在上一小節中看到,在必要的時候,int 類型地值將會自動地轉換爲double類型。但另外一方面,有時也須要將double轉換成int。在Java中,容許進行這種數值之間的類型轉換。固然,有可能會丟失一些信息。在這種狀況下,須要經過強制類型轉換(cast)實現這個操做。強制類型轉換地格式是在圓括號中給出想要轉換地目標類型,後面緊跟待轉換地變量名。例如:
double x = 9.997; int nx = (int) x; // nx is 9
這樣,變量nx的值爲9。強制類型轉換經過截斷小數部分將浮點型轉換爲整型。
若是想對浮點數進行攝入運算,以便的到最接近的整數,那就須要使用Math.round()方法:
double x = 9.997; int nx = (int) Math.round(x); // nx is 10
如今,變量nx的值爲10。當調用round的時候,仍然須要強制類型轉換(int)。其緣由是round方法返回的結果是long類型,因爲存在信息丟失的可能性,因此只有使用顯式的強制類型轉換纔可以將long類型轉換成int 類型。
3.5.4 結合賦值和運算符
能夠在賦值中使用二元運算符,這是種很簡便的方式。例如:
x += 4;
等價於:
x = x + 4;
(通常的,要把運算符放在=號左邊,如*=或%=)。
註釋:若是運算符獲得一個值,其類型與左側操做數的類型不一樣,就會發生強制類型轉換。例如,若是 x 是一個int,則如下語句:
x += 3.5;
是合法的,將把x 設置爲(int)(x + 3.5)。
3.5.5 自增與自減運算符
因爲自增,自減運算符會改變變量的值,因此他們的操做數不能是數值。例如, 4++; 就不是一個合法的語句。
運算符放在操做數後面是「後綴」形式,如: n++;
運算符放在操做數前面是「前綴」形式,如: ++n;
前綴形式會先完成加1,然後綴形式會使用變量原來的值。
int m = 7; int n = 7; int a = 2 * ++m; int b = 2 * n++; System.out.println("a now is :" + a +",and m now is "+m); // a now is :16,and m now is 8 System.out.println("b now is :" + b +",and n now is "+n); // b now is :14,and n now is 8
建議不要在表達式中使用++,由於這樣的代碼很容易讓人困惑,並且會帶來煩人的bug。
3.5.6 關係和boolean運算符
Java支持三元操做符?: ,這個操做符又是頗有用。若是條件爲true,下面的表達式
condition ? expression1 : expression2
就爲第一個表達式的值,不然計算爲第二個表達式的值。例如:
int x = 3; int y = 4; int nx = x < y ? x : y; System.out.println(nx);
會返回x 和 y 中較小的一個。
3.5.7 位運算符
處理整型類型時,能夠直接對組成整型數值的各個位完成操做。這意味着可使用掩碼技術獲得整數中的各個位。位運算符包括:
&("and") | ("or") ^ ("xor") ~ ("not")
這些運算符按位模式處理。例如,若是n是一個整數變量,並且用二進制表示的n 從右邊數第4位爲1,則:
int n = 8; int fourthBitFromRight = (n & 0b1000) / 0b1000; System.out.println(fourthBitFromRight); // 1 由於十進制 8 用二進制表示爲 1000 int m = 4; fourthBitFromRight = (m & 0b1000) / 0b1000; // 0 由於十進制 4 用二進制表示爲 0100 System.out.println(fourthBitFromRight);
會返回1,不然返回0。利用& 並結合使用適當的 2 的冪,能夠把其餘位掩掉,而只保留其中一位。
註釋:應用在布爾值上,& 和 | 運算符也會獲得布爾值。這些運算符與 && 和 || 運算符很相似,不過 & 和 | 運算符不採用「短路」方式求值,也就是說,獲得計算結果以前兩個操做數都須要計算。
另外,還有 >> 和 << 運算符將位模式左移或右移。須要創建位模式來完成位掩碼,這兩個運算符很方便:
int n = 4; int fourBitFromRight = (n & (1 << 3)) >> 3; System.out.println(fourBitFromRight); // 0
最後,>>> 運算符會用0 填充高位,這與 >> 不一樣,它會用符號位填充高位。不存在 <<< 運算符。
警告:位移運算符的有操做要完成模32的運算,(除非左操做數是long類型,在這種狀況下須要對右操做數模64)。例如,1<<35 的值等同於 1 << 3或8。
3.5.8 括號與運算符級別
同一級別的運算符按照從左到右的次序依次計算(除了表中給出的右結合運算符外)。例如:因爲&&的優先級比||的優先級高,因此表達式
a && b || c ;
等價於
(a && b)|| c ;
又由於 += 是右結合運算符,因此表達式
a += b += c;
等價於
a += (b += c) ;
也就是將 b += c的結果(加上c以後的b)加到 a 上。
運算符 | 結合性 |
[].() (方法調用) | 從左至右 |
! ~ ++ -- +(一元運算) - (一元運算) () (強制類型轉換) new | 從右至左 |
* / % | 從左至右 |
+ - | 從左至右 |
<< >> >>> | 從左至右 |
< <= > >= instanceof | 從左至右 |
== != | 從左至右 |
& | 從左至右 |
^ | 從左至右 |
| | 從左至右 |
&& | 從左至右 |
|| | 從左至右 |
?: | 從右至左 |
= += -= *= /= %= &= |= ^= <<= >>= >>>= | 從右至左 |
3.5.9 枚舉類型
3.6 字符串
從概念上講,Java字符串就是Unicode字符串序列。例如,串「Java\u2122」 由5個Unicode字符 J、a、v、a、和™。Java沒有內置的字符串類型,而是在標準Java類庫中提供了一個預約義類,很天然地叫作String。
3.6.1 子串
String類的substring方法能夠從一個較大的字符串提取出一個字串。
String greeting = "Hello"; String s = greeting.substring(0,3); // Hel
substring方法的第二個參數是不想複製的第一個位置。這裏要複製位置爲0、一、2(從0到2,包括0和2)的字符。在substring中從0開始計數,直到3爲止,但不包含3。
substring的工做方式有一個優勢:容易計算子串的長度。字符串s.substring(a,b)的長度爲b-a。例如,子串「Hel」的長度爲3-0=3。
3.6.2 拼接
若是須要把多個字符串放在一塊兒,用一個定界符分隔,可使用靜態join方法:
String all = String.join(" / ","S","M","L","XL"); System.out.println("all is the string : \""+all+"\"");
// all is the string : "S / M / L / XL"
3.6.3 不可變字符串
String類沒有提供用於修改字符串的方法。若是但願將greeting的內容改成"Help!",不能直接將greeting的最後兩個位置的字符串修改成‘p’和‘!’。在Java中實現這項操做很是容易。首先提取須要的字符,而後在拼接上替換的字符串:
String greeting = "Hello"; greeting = greeting.substring(0,3) + "p!"; System.out.println("greeting is changed to \"" + greeting +"\""); // greeting is changed to "Help!"
因爲不能修改Java字符串中的字符,因此在Java文檔中將String類對象稱爲不可變字符串,如同數字3永遠是數字3同樣,字符串「Hello」永遠包含字符H、e、l、l 和 o 的代碼單元序列,而不能修改其中的任何一個字符。固然,能夠修改字符串變量greeting,讓它引用另一個字符串,這就如同能夠將存放3的數值變量改爲存放4同樣。
不可變字符串卻有一個優勢:編譯器可讓字符串共享。
3.6.4 檢查字符串是否相等
可使用equals方法檢測兩個字符串是否相等。對於表達式:
s.equals(t)
若是字符串s與字符串t相等則返回true;不然返回false。須要注意,s與t 能夠是字符串變量,也能夠是字符串字面量。例如,下面的表達式是合法的:
"Hello".equals(greeting);
要想檢測兩個字符串是否相等,而不區分大小寫,可使用equalsIgnoreCase方法。
"Hello".equalsIgnoreCase(greeting);
必定不要使用==運算符檢測兩個字符串是否相等!這個運算符只可以肯定兩個字符串是否放置的在同一個位置上。固然,若是字符串放置在同一個位置上,他們必然相等。可是徹底有可能將內容相同的多個字符串的拷貝放置在不一樣的位置上。
String greeting = "Hello"; // initailize greeting to a string if (greeting == "Hello"){ System.out.println("greeting == \"Hello\""); // greeting == "Hello" }else { System.out.println("greeting != \"Hello\""); } if (greeting.substring(0,3) == "Hel"){ System.out.println("greeting.substring(0,3) == \"Hello\""); }else { System.out.println("greeting.substring(0,3) != \"Hello\""); // greeting.substring(0,3) != "Hello" }
若是虛擬機始終將相同的字符串共享,就可使用==運算符檢測是否相等。但實際上只有字符串常量是共享的,而+或substring等操做產生的結果並非共享的。所以,千萬不要使用==運算符測試字符串的相等性,以避免在程序中出現糟糕的bug。
3.6.5 空串與Null串
空串""是長度爲0的字符串,能夠調用如下代碼檢查一個字符串是否爲空:
String str = ""; if (str.length() == 0 && str.equals("")){ System.out.println("str is \"\""); }
固然 str.length() == 0 或 str.equals("") 均可以檢驗一個字符串是否爲空。
空串是一個Java對象,有本身的串長度(0)和內容(空)。不過,String變量還能夠存放一個特殊的值,名爲null,這表示目前沒有任何對象與該變量關聯。
有時要檢查一個字符串既不是null也不爲空串,這種狀況下要使用如下條件,注意檢查的前後順序:
if (str != null && str.length() != 0)
3.66 碼點與代碼單元
Java字符串由char值序列組成。char數據類型是一個採用UTF-16編碼表示的Unicode碼點的代碼單元。大多數經常使用Unicode字符使用一個代碼單元就能夠表示,而輔助字符須要一對代碼單元表示。
length方法將返回採用UTF-16編碼表示的給定字符串所須要的代碼單元數量例如:
String greeting = "Hello"; int n = greeting.length(); // n is 5
要想獲得實際的長度,即碼點數量,能夠調用:
String greeting = "Hello"; int cpCount = greeting.codePointCount(0, greeting.length()); System.out.println("cpCount is "+ cpCount); // cpCount is 5
調用s.charAt(n)將返回位置n的代碼單元, n 介於0 ~ s.length()-1 之間。
3.7.2 printf
3.7.3 文件輸入與輸出
文件讀取:
Scanner in = new Scanner(Paths.get("myfile.txt"),"UTF-8");
文件寫入:
PrintWriter out = new PrintWriter("myfile.txt", "UTF-8");
能夠用下面的調用方式找到路徑的位置:
System.getProperty("user.dir")
3.8.3 循環
程序清單3-3 Retirement/Retirement.Java
while(){}
public class Retirement { public static void main(String[] args) { // read inputs Scanner in = new Scanner(System.in); System.out.print("How much money do you need to retire? "); double goal = in.nextDouble(); System.out.print("How much money will you contribute every year? "); double payment = in.nextDouble(); System.out.print("Interest rate in %: "); double interestRate = in.nextDouble(); double balance = 0; int years = 0; // update account balance while goal isn't reached while (balance < goal) { // add this year's payment and interest balance += payment; double interest = balance * interestRate / 100; balance += interest; years++; } System.out.println("You can retire in " + years + " years"); } }
do{......}while(boolean)
public class Retirement2 { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("How much money will you contribute every year? "); double payment = in.nextDouble(); System.out.print("Interest rate is %: "); double interestRate = in.nextDouble(); double balance = 0; int year = 0; String input; // update account balance while user isn't ready to retire do { // add this year's payment and interest balance += payment; double interest = balance * interestRate / 100; balance += interest; year++; // print current balance System.out.printf("After year %d, your balance is %,.2f%n", year, balance); // ask if ready to retire and get input System.out.println("Reday to retire? (Y/N) "); input = in.next(); } while (input.equals("N")); } }
3.8.4 肯定循環
do/while
for
for語句是while循環的一種簡化形式。
for (int i = 10; i > 0; i--){ System.out.println("Counting down for... " + i); }
// 可重寫爲: int i = 10; while (i > 0){ System.out.println("Counting down while ... " + i); i--; }
程序清單3-5 LotteryOdds/LotteryOdds.java
public class LotteryOdds { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("How many numbers do you need to draw? "); int k = in.nextInt(); System.out.println("What is the highest number you can draw? "); int n = in.nextInt(); /** * compute binomial coefficient n*(n-1)*(n-2)*...*(n-k+1)/(1*2*3*...*k) */ int lotterOdds = 1; for (int i = 1; i <= k; i++){ lotterOdds = lotterOdds * (n - i + 1) / i; } System.out.println("Your odds are 1 in " + lotterOdds + ". Good luck!"); } }