參考:http://www.runoob.com/java/java-tutorial.htmljavascript
Java 基本數據類型html
內置數據類型java
引用類型mysql
Java 變量類型linux
Java 局部變量c++
實例變量git
類變量(靜態變量)程序員
Java 修飾符web
默認訪問修飾符-不使用任何關鍵字正則表達式
appendReplacement 和 appendTail 方法
Java 重寫(Override)與重載(Overload)
byte:
l byte 數據類型是8位、有符號的,以二進制補碼錶示的整數;
l 最小值是 -128(-2^7);
l 最大值是 127(2^7-1);
l 默認值是 0;
l byte 類型用在大型數組中節約空間,主要代替整數,由於 byte 變量佔用的空間只有 int 類型的四分之一;
l 例子:byte a = 100,byte b = -50。
float:
l float 數據類型是單精度、32位、符合IEEE 754標準的浮點數;
l float 在儲存大型浮點數組的時候可節省內存空間;
l 默認值是 0.0f;
l 浮點數不能用來表示精確的值,如貨幣;
l 例子:float f1 = 234.5f。
double:
l double 數據類型是雙精度、64 位、符合IEEE 754標準的浮點數;
l 浮點數的默認類型爲double類型;
l double類型一樣不能表示精確的值,如貨幣;
l 默認值是 0.0d;
l 例子:double d1 = 123.4。
char:
l char類型是一個單一的 16 位 Unicode 字符;
l 最小值是 \u0000(即爲0);
l 最大值是 \uffff(即爲65,535);
l char 數據類型能夠儲存任何字符;
l 例子:char letter = 'A';。
l 在Java中,引用類型的變量很是相似於C/C++的指針。引用類型指向一個對象,指向對象的變量是引用變量。這些變量在聲明時被指定爲一個特定的類型,好比 Employee、Puppy 等。變量一旦聲明後,類型就不能被改變了。
l 對象、數組都是引用數據類型。
l 全部引用類型的默認值都是null。
l 一個引用變量能夠用來引用任何與之兼容的類型。
l 例子:Site site = new Site("Runoob")。
byte,short,char—> int —> long—> float —> double
數據類型轉換必須知足以下規則:
l 1. 不能對boolean類型進行類型轉換。
l 2. 不能把對象類型轉換成不相關類的對象。
l 3. 在把容量大的類型轉換爲容量小的類型時必須使用強制類型轉換。
l 4. 轉換過程當中可能致使溢出或損失精度,例如:
l 5. 浮點數到整數的轉換是經過捨棄小數獲得,而不是四捨五入,例如:
(int)23.7 == 23; (int)-45.89f == -45
隱含強制類型轉換
l 1. 整數的默認類型是 int。
l 2. 浮點型不存在這種狀況,由於在定義 float 類型時必須在數字後面跟上 F 或者 f。
Java語言支持的變量類型有:
l 類變量:獨立於方法以外的變量,用 static 修飾。
l 實例變量:獨立於方法以外的變量,不過沒有 static 修飾。
l 局部變量:類的方法中的變量。
public class Variable{ static int allClicks=0; // 類變量 String str="hello world"; // 實例變量 public void method(){ int i =0; // 局部變量 } }
l 局部變量聲明在方法、構造方法或者語句塊中;
l 局部變量在方法、構造方法、或者語句塊被執行的時候建立,當它們執行完成後,變量將會被銷燬;
l 訪問修飾符不能用於局部變量;
l 局部變量只在聲明它的方法、構造方法或者語句塊中可見;
l 局部變量是在棧上分配的。
l 局部變量沒有默認值,因此局部變量被聲明後,必須通過初始化,纔可使用。
l 實例變量聲明在一個類中,但在方法、構造方法和語句塊以外;
l 當一個對象被實例化以後,每一個實例變量的值就跟着肯定;
l 實例變量在對象建立的時候建立,在對象被銷燬的時候銷燬;
l 實例變量的值應該至少被一個方法、構造方法或者語句塊引用,使得外部可以經過這些方式獲取實例變量信息;
l 實例變量能夠聲明在使用前或者使用後;
l 訪問修飾符能夠修飾實例變量;
l 實例變量對於類中的方法、構造方法或者語句塊是可見的。通常狀況下應該把實例變量設爲私有。經過使用訪問修飾符可使實例變量對子類可見;
l 實例變量具備默認值。數值型變量的默認值是0,布爾型變量的默認值是false,引用類型變量的默認值是null。變量的值能夠在聲明時指定,也能夠在構造方法中指定;
l 實例變量能夠直接經過變量名訪問。但在靜態方法以及其餘類中,就應該使用徹底限定名:ObejectReference.VariableName。
l 類變量也稱爲靜態變量,在類中以static關鍵字聲明,但必須在方法構造方法和語句塊以外。
l 不管一個類建立了多少個對象,類只擁有類變量的一份拷貝。
l 靜態變量除了被聲明爲常量外不多使用。常量是指聲明爲public/private,final和static類型的變量。常量初始化後不可改變。
l 靜態變量儲存在靜態存儲區。常常被聲明爲常量,不多單獨使用static聲明變量。
l 靜態變量在第一次被訪問時建立,在程序結束時銷燬。
l 與實例變量具備類似的可見性。但爲了對類的使用者可見,大多數靜態變量聲明爲public類型。
l 默認值和實例變量類似。數值型變量默認值是0,布爾型默認值是false,引用類型默認值是null。變量的值能夠在聲明的時候指定,也能夠在構造方法中指定。此外,靜態變量還能夠在靜態語句塊中初始化。
l 靜態變量能夠經過:ClassName.VariableName的方式訪問。
l 類變量被聲明爲public static final類型時,類變量名稱通常建議使用大寫字母。若是靜態變量不是public和final類型,其命名方式與實例變量以及局部變量的命名方式一致。
修飾符 |
當前類 |
同一包內 |
子孫類(同一包) |
子孫類(不一樣包) |
其餘包 |
public |
Y |
Y |
Y |
Y |
Y |
protected |
Y |
Y |
Y |
Y/N(說明) |
N |
default |
Y |
Y |
Y |
N |
N |
private |
Y |
N |
N |
N |
N |
default (即缺省,什麼也不寫): 在同一包內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。
使用默認訪問修飾符聲明的變量和方法,對同一個包內的類是可見的。接口裏的變量都隱式聲明爲 public static final,而接口裏的方法默認狀況下訪問權限爲 public。
被聲明爲 public 的類、方法、構造方法和接口可以被任何其餘類訪問。
若是幾個相互訪問的 public 類分佈在不一樣的包中,則須要導入相應 public 類所在的包。因爲類的繼承性,類全部的公有方法和變量都能被其子類繼承。
如下函數使用了公有訪問控制:
public static void main(String[] arguments) { // ...}
Java 程序的 main() 方法必須設置成公有的,不然,Java 解釋器將不能運行該類。
protected 是最難理解的一種 Java 類成員訪問權限修飾詞,更多詳細內容請查看 Java protected 關鍵字詳解。
protected 須要從如下兩個點來分析說明:
l 子類與基類在同一包中:被聲明爲 protected 的變量、方法和構造器能被同一個包中的任何其餘類訪問;
l 子類與基類不在同一包中:那麼在子類中,子類實例能夠訪問其從基類繼承而來的 protected 方法,而不能訪問基類實例的protected方法。
l 接口及接口的成員變量和成員方法不能聲明爲 protected。
請注意如下方法繼承的規則(只能降級):
l 父類中聲明爲 public 的方法在子類中也必須爲 public。
l 父類中聲明爲 protected 的方法在子類中要麼聲明爲 protected,要麼聲明爲 public,不能聲明爲 private。
l 父類中聲明爲 private 的方法,不可以被繼承。
爲了實現一些其餘的功能,Java 也提供了許多非訪問修飾符。
static 修飾符,用來修飾類方法和類變量。
final 修飾符,用來修飾類、方法和變量,final 修飾的類不可以被繼承,修飾的方法不能被繼承類從新定義,修飾的變量爲常量,是不可修改的。
abstract 修飾符,用來建立抽象類和抽象方法。
synchronized 和 volatile 修飾符,主要用於線程的編程
final 變量:
final 表示"最後的、最終的"含義,變量一旦賦值後,不能被從新賦值。被 final 修飾的實例變量必須顯式指定初始值。
final 修飾符一般和 static 修飾符一塊兒使用來建立類常量。
final 方法
類中的 final 方法能夠被子類繼承,可是不能被子類修改。
聲明 final 方法的主要目的是防止該方法的內容被修改。
抽象類:
抽象類不能用來實例化對象,聲明抽象類的惟一目的是爲了未來對該類進行擴充。
一個類不能同時被 abstract 和 final 修飾。若是一個類包含抽象方法,那麼該類必定要聲明爲抽象類,不然將出現編譯錯誤。
抽象類能夠包含抽象方法和非抽象方法。
抽象方法
抽象方法是一種沒有任何實現的方法,該方法的的具體實現由子類提供。
抽象方法不能被聲明成 final 和 static。
任何繼承抽象類的子類必須實現父類的全部抽象方法,除非該子類也是抽象類。
若是一個類包含若干個抽象方法,那麼該類必須聲明爲抽象類。抽象類能夠不包含抽象方法。
抽象方法的聲明以分號結尾,例如:public abstract sample();。
synchronized 關鍵字聲明的方法同一時間只能被一個線程訪問。synchronized 修飾符能夠應用於四個訪問修飾符。
序列化的對象包含被 transient 修飾的實例變量時,java 虛擬機(JVM)跳過該特定的變量。
該修飾符包含在定義變量的語句中,用來預處理類和變量的數據類型。
volatile 修飾的成員變量在每次被線程訪問時,都強制從共享內存中從新讀取該成員變量的值。並且,當成員變量發生變化時,會強制線程將變化值回寫到共享內存。這樣在任什麼時候刻,兩個不一樣的線程老是看到某個成員變量的同一個值。
一個 volatile 對象引用多是 null。
當使用與邏輯運算符時,在兩個操做數都爲true時,結果才爲true,可是當獲得第一個操做爲false時,其結果就一定是false,這時候就不會再判斷第二個操做了。
該運算符用於操做對象實例,檢查該對象是不是一個特定類型(類類型或接口類型)。
instanceof運算符使用格式以下:
( Object reference variable ) instanceof (class/interface type)
若是運算符左側變量所指的對象,是操做符右側類或接口(class/interface)的一個對象,那麼結果爲真。
下面是一個例子:
String name = "James";boolean result = name instanceof String; // 因爲 name 是 String 類型,因此返回真
一元 |
+ + - !〜 |
從右到左 |
條件 |
?: |
從右到左 |
賦值 |
= + = - = * = / =%= >> = << =&= ^ = | = |
從右到左 |
Java5 引入了一種主要用於數組的加強型 for 循環。
Java 加強 for 循環語法格式以下:
for(聲明語句 : 表達式){ //代碼句子}int [] numbers = {10, 20, 30, 40, 50}; for(int x : numbers ){ System.out.print( x ); System.out.print(","); }
聲明語句:聲明新的局部變量,該變量的類型必須和數組元素的類型匹配。其做用域限定在循環語句塊,其值與此時數組元素的值相等。
表達式:表達式是要訪問的數組名,或者是返回值爲數組的方法。
switch case 執行時,必定會先進行匹配,匹配成功返回當前 case 的值,再根據是否有 break,判斷是否繼續輸出,或是跳出判斷。
若是 case 語句塊中沒有 break 語句時,JVM 並不會順序輸出每個 case 對應的返回值,而是繼續匹配,匹配不成功則返回默認 case。
若是當前匹配成功的 case 語句塊沒有 break 語句,則從當前 case 開始,後續全部 case 的值都會輸出,若是後續的 case 語句塊有 break 語句則會跳出判斷。
全部的包裝類(Integer、Long、Byte、Double、Float、Short)都是抽象類 Number 的子類。
當 x 被賦爲整型值時,因爲x是一個對象,因此編譯器要對x進行裝箱。而後,爲了使x能進行加運算,因此要對x進行拆箱。
Math 的方法都被定義爲 static 形式,經過 Math 類能夠在主函數中直接調用。
序號 |
方法與描述 |
1 |
將 Number 對象轉換爲xxx數據類型的值並返回。 |
2 |
將number對象與參數比較。 |
3 |
判斷number對象是否與參數相等。 |
4 |
返回一個 Number 對象指定的內置數據類型 |
5 |
以字符串形式返回值。 |
6 |
將字符串解析爲int類型。 |
10 |
返回與參數最接近的整數。返回類型爲double。 |
intValue() :以 int 形式返回指定的數值。
l Integer valueOf(int i):返回一個表示指定的 int 值的 Integer 實例。
l Integer valueOf(String s):返回保存指定的 String 的值的 Integer 對象。
l Integer valueOf(String s, int radix): 返回一個 Integer 對象,該對象中保存了用第二個參數提供的基數進行解析時從指定的 String 中提取的值。
Integer b = Integer.valueOf("444",16); // 使用 16 進制,=1092
將一個char類型的參數傳遞給須要一個Character類型參數的方法時,那麼編譯器會自動地將char類型參數轉換爲Character對象。 這種特徵稱爲裝箱,反過來稱爲拆箱。
序號 |
方法與描述 |
1 |
是不是一個字母 |
2 |
是不是一個數字字符 |
3 |
是不是一個空白字符 |
4 |
是不是大寫字母 |
5 |
是不是小寫字母 |
6 |
指定字母的大寫形式 |
7 |
指定字母的小寫形式 |
8 |
toString() 返回字符的字符串形式,字符串的長度僅爲1 |
建立字符串最簡單的方式以下:
String greeting = "菜鳥教程";
在代碼中遇到字符串常量時,這裏的值是 "菜鳥教程"",編譯器會使用該值建立一個 String 對象。
和其它對象同樣,可使用關鍵字和構造方法來建立 String 對象。
String 類有 11 種構造方法,這些方法提供不一樣的參數來初始化字符串,好比提供一個字符數組參數:
注意:String 類是不可改變的,因此你一旦建立了 String 對象,那它的值就沒法改變了(詳看筆記部分解析)。
若是須要對字符串作不少修改,那麼應該選擇使用 StringBuffer & StringBuilder 類。
如下是 StringBuffer 類支持的主要方法:
序號 |
方法描述 |
1 |
public StringBuffer append(String s) 將指定的字符串追加到此字符序列。 |
2 |
public StringBuffer reverse() 將此字符序列用其反轉形式取代。 |
3 |
public delete(int start, int end) 移除此序列的子字符串中的字符。 |
4 |
public insert(int offset, int i) 將 int 參數的字符串表示形式插入此序列中。 |
5 |
replace(int start, int end, String str) 使用給定 String 中的字符替換此序列的子字符串中的字符。 |
咱們知道輸出格式化數字可使用 printf() 和 format() 方法。
String 類使用靜態方法 format() 返回一個String 對象而不是 PrintStream 對象。
String 類的靜態方法 format() 能用來建立可複用的格式化字符串,而不只僅是用於一次打印輸出。
以下所示:
System.out.printf("浮點型變量的值爲 " + "%f, 整型變量的值爲 " + " %d, 字符串變量的值爲 " + "is %s", floatVar, intVar, stringVar);//你也能夠這樣寫String fs;fs = String.format("浮點型變量的值爲 " + "%f, 整型變量的值爲 " + " %d, 字符串變量的值爲 " + " %s", floatVar, intVar, stringVar);
下面是 String 類支持的方法,更多詳細,參看 Java String API 文檔:
SN(序號) |
方法描述 |
1 |
返回指定索引處的 char 值。 |
2 |
把這個字符串和另外一個對象比較。 |
3 |
int compareTo(String anotherString) 按字典順序比較兩個字符串。 |
4 |
int compareToIgnoreCase(String str) 按字典順序比較兩個字符串,不考慮大小寫。 |
5 |
將指定字符串鏈接到此字符串的結尾。 |
6 |
boolean contentEquals(StringBuffer sb) 當且僅當字符串與指定的StringBuffer有相同順序的字符時候返回真。 |
7 |
static String copyValueOf(char[] data) 返回指定數組中表示該字符序列的 String。 |
9 |
boolean endsWith(String suffix) 測試此字符串是否以指定的後綴結束。 |
10 |
boolean equals(Object anObject) 將此字符串與指定的對象比較。 |
11 |
boolean equalsIgnoreCase(String anotherString) 將此 String 與另外一個 String 比較,不考慮大小寫。 |
16 |
返回指定字符在此字符串中第一次出現處的索引。 |
17 |
int indexOf(int ch, int fromIndex) 返回在此字符串中第一次出現指定字符處的索引,從指定的索引開始搜索。 |
18 |
返回指定子字符串在此字符串中第一次出現處的索引。 |
19 |
int indexOf(String str, int fromIndex) 返回指定子字符串在此字符串中第一次出現處的索引,從指定的索引開始。 |
21 |
返回指定字符在此字符串中最後一次出現處的索引。 |
22 |
int lastIndexOf(int ch, int fromIndex) 返回指定字符在此字符串中最後一次出現處的索引,從指定的索引處開始進行反向搜索。 |
23 |
返回指定子字符串在此字符串中最右邊出現處的索引。 |
24 |
int lastIndexOf(String str, int fromIndex) 返回指定子字符串在此字符串中最後一次出現處的索引,從指定的索引開始反向搜索。 |
25 |
返回此字符串的長度。 |
26 |
告知此字符串是否匹配給定的正則表達式。 |
29 |
String replace(char oldChar, char newChar) 返回一個新的字符串,它是經過用 newChar 替換此字符串中出現的全部 oldChar 獲得的。 |
30 |
String replaceAll(String regex, String replacement) 使用給定的 replacement 替換此字符串全部匹配給定的正則表達式的子字符串。 |
31 |
String replaceFirst(String regex, String replacement) 使用給定的 replacement 替換此字符串匹配給定的正則表達式的第一個子字符串。 |
32 |
根據給定正則表達式的匹配拆分此字符串。 |
33 |
String[] split(String regex, int limit) 根據匹配給定的正則表達式來拆分此字符串。 |
34 |
boolean startsWith(String prefix) 測試此字符串是否以指定的前綴開始。 |
35 |
boolean startsWith(String prefix, int toffset) 測試此字符串從指定索引開始的子字符串是否以指定前綴開始。 |
36 |
CharSequence subSequence(int beginIndex, int endIndex) 返回一個新的字符序列,它是此序列的一個子序列。 |
37 |
String substring(int beginIndex) 返回一個新的字符串,它是此字符串的一個子字符串。 |
38 |
String substring(int beginIndex, int endIndex) 返回一個新字符串,它是此字符串的一個子字符串。 |
39 |
將此字符串轉換爲一個新的字符數組。 |
40 |
使用默認語言環境的規則將此 String 中的全部字符都轉換爲小寫。 |
41 |
String toLowerCase(Locale locale) 使用給定 Locale 的規則將此 String 中的全部字符都轉換爲小寫。 |
42 |
返回此對象自己(它已是一個字符串!)。 |
43 |
使用默認語言環境的規則將此 String 中的全部字符都轉換爲大寫。 |
44 |
String toUpperCase(Locale locale) 使用給定 Locale 的規則將此 String 中的全部字符都轉換爲大寫。 |
45 |
注意: 建議使用 dataType[] arrayRefVar 的聲明風格聲明數組變量。 dataType arrayRefVar[] 風格是來自 C/C++ 語言 ,在Java中採用是爲了讓 C/C++ 程序員可以快速理解java語言。
java 裏面爲何數組都須要new一下?而C++不須要
java 數組所引用的值,是在堆裏的,
java 數組是引用對象,引用對象都須要開闢內存空間,
new 關鍵字在java裏是實例化對象,也是爲對象開闢內存空間
其實也不必定要new, int[] arr = {}; 這樣也是能夠的
若是大括號裏不賦值,就是個空數組,大括號裏賦幾個值,這個數組就是多大
c / c++ 也是這樣用
int arr1[] = {1,2,3,4,5,6};
int arr2[50] = {-23,34,56,100,234,-9,0,45,10002};
只是,c/c++ 聲明時能夠指定大小,
JAVA 裏面的數組名是一個引用變量,引用變量是放在是放在一個棧裏面,而JAVA數組自己就是對象,Java中對象是在堆中的,所以數組不管保存原始類型仍是其餘對象類型,數組對象自己是在堆中的。因此若是不new一下,就沒法獲得這個數組,即引用變量沒有引用的對象。而在C++中,數組名其實是數組的首地址,是一個指針,數組在聲明以後就已經生成了這個數組對象。就不用new了
下面的語句首先聲明瞭一個數組變量 myList,接着建立了一個包含 10 個 double 類型元素的數組,而且把它的引用賦值給 myList 變量。
// 數組大小 int size = 10; // 定義數組 double[] myList = new double[size]; myList[0] = 5.6;//……
引用和指針的區別?
指針是一個變量,只不過這個變量存儲的是一個地址,指向內存的一個存儲單元;而引用跟原來的變量實質上是同一個東西,只不過是原變量的一個別名而已。
本質:引用是別名,指針是地址,具體的:
①從現象上看,指針在運行時能夠改變其所指向的值,而引用一旦和某個對象綁定後就再也不改變。這句話能夠理解爲:指針能夠被從新賦值以指向另外一個不一樣的對象。可是引用則老是指向在初始化時被指定的對象,之後不能改變,可是指定的對象其內容能夠改變。
②從內存分配上看,程序爲指針變量分配內存區域,而不爲引用分配內存區域,由於引用聲明時必須初始化,從而指向一個已經存在的對象。引用不能指向空值。
注:標準沒有規定引用要不要佔用內存,也沒有規定引用具體要怎麼實現,具體隨編譯器 http://bbs.csdn.net/topics/320095541
③ 從編譯上看,程序在編譯時分別將指針和引用添加到符號表上,符號表上記錄的是變量名及變量所對應地址。指針變量在符號表上對應的地址值爲指針變量的地址值,而引用在符號表上對應的地址值爲引用對象的地址值。符號表生成後就不會再改,所以指針能夠改變指向的對象(指針變量中的值能夠改),而引用對象不能改。這是使用指針不安全而使用引用安全的主要緣由。從某種意義上來講引用能夠被認爲是不能改變的指針。
④不存在指向空值的引用這個事實,意味着使用引用的代碼效率比使用指針的要高。由於在使用引用以前不須要測試它的合法性。相反,指針則應該老是被測試,防止其爲空。
⑤理論上,對於指針的級數沒有限制,可是引用只能是一級。
java.util.Arrays 類能方便地操做數組,它提供的全部方法都是靜態的。
具備如下功能:
l 給數組賦值:經過 fill 方法。
l 對數組排序:經過 sort 方法,按升序。
l 比較數組:經過 equals 方法比較數組中元素值是否相等。
l 查找數組元素:經過 binarySearch 方法能對排序好的數組進行二分查找法操做。
序號 |
方法和描述 |
1 |
boolean after(Date date) 若當調用此方法的Date對象在指定日期以後返回true,不然返回false。 |
2 |
boolean before(Date date) 若當調用此方法的Date對象在指定日期以前返回true,不然返回false。 |
3 |
Object clone( ) 返回此對象的副本。 |
4 |
int compareTo(Date date) 比較當調用此方法的Date對象和指定日期。二者相等時候返回0。調用對象在指定日期以前則返回負數。調用對象在指定日期以後則返回正數。 |
5 |
int compareTo(Object obj) 若obj是Date類型則操做等同於compareTo(Date) 。不然它拋出ClassCastException。 |
6 |
boolean equals(Object date) 當調用此方法的Date對象和指定日期相等時候返回true,不然返回false。 |
7 |
long getTime( ) 返回自 1970 年 1 月 1 日 00:00:00 GMT 以來此 Date 對象表示的毫秒數。 |
8 |
int hashCode( ) 返回此對象的哈希碼值。 |
9 |
void setTime(long time)
用自1970年1月1日00:00:00 GMT之後time毫秒數設置時間和日期。 |
10 |
String toString( ) 把此 Date 對象轉換爲如下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一週中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。 |
Date dNow = new Date( );SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");System.out.println("當前時間爲: " + ft.format(dNow));
printf 方法能夠很輕鬆地格式化時間和日期。使用兩個字母格式,它以 %t 開頭而且如下面表格中的一個字母結尾。
轉 換 符 |
說 明 |
示 例 |
c |
包括所有日期和時間信息 |
星期六 十月 27 14:21:20 CST 2007 |
F |
"年-月-日"格式 |
2007-10-27 |
D |
"月/日/年"格式 |
10/27/07 |
r |
"HH:MM:SS PM"格式(12時制) |
02:25:51 下午 |
T |
"HH:MM:SS"格式(24時制) |
14:28:16 |
R |
"HH:MM"格式(24時制) |
14:28 |
SimpleDateFormat 類有一些附加的方法,特別是parse(),它試圖按照給定的SimpleDateFormat 對象的格式化存儲來解析字符串。
java.util.regex 包主要包括如下三個類:
l Pattern 類:
pattern 對象是一個正則表達式的編譯表示。Pattern 類沒有公共構造方法。要建立一個 Pattern 對象,你必須首先調用其公共靜態編譯方法,它返回一個 Pattern 對象。該方法接受一個正則表達式做爲它的第一個參數。
l Matcher 類:
Matcher 對象是對輸入字符串進行解釋和匹配操做的引擎。與Pattern 類同樣,Matcher 也沒有公共構造方法。你須要調用 Pattern 對象的 matcher 方法來得到一個 Matcher 對象。
l PatternSyntaxException:
PatternSyntaxException 是一個非強制異常類,它表示一個正則表達式模式中的語法錯誤。
注意:在 Java 中正則表達式中則須要有兩個反斜槓才能被解析爲其餘語言中的轉義做用。也能夠簡單的理解在 Java 的正則表達式中,兩個 \\ 表明其餘語言中的一個 \,這也就是爲何表示一位數字的正則表達式是 \\d,而表示一個普通的反斜槓是 \\\\。
根據 Java Language Specification 的要求,Java 源代碼的字符串中的反斜線被解釋爲 Unicode 轉義或其餘字符轉義。所以必須在字符串字面值中使用兩個反斜線,表示正則表達式受到保護,不被 Java 字節碼編譯器解釋。例如,當解釋爲正則表達式時,字符串字面值 "\b" 與單個退格字符匹配,而 "\\b" 與單詞邊界匹配。字符串字面值 "\(hello\)" 是非法的,將致使編譯時錯誤;要與字符串 (hello) 匹配,必須使用字符串字面值 "\\(hello\\)"。
// 按指定模式在字符串查找 String line = "This order was placed for QT3000! OK?"; String pattern = "(\\D*)(\\d+)(.*)"; // 建立 Pattern 對象 Pattern r = Pattern.compile(pattern); // 如今建立 matcher 對象 Matcher m = r.matcher(line);
matches 和 lookingAt 方法都用來嘗試匹配一個輸入序列模式。它們的不一樣是 matches 要求整個序列都匹配,而lookingAt 不要求。
lookingAt 方法雖然不須要整句都匹配,可是須要從第一個字符開始匹配。
replaceFirst 和 replaceAll 方法用來替換匹配正則表達式的文本。不一樣的是,replaceFirst 替換首次匹配,replaceAll 替換全部匹配。
Matcher 類也提供了appendReplacement 和 appendTail 方法用於文本替換
System.out.println(),那麼它是什麼呢?
l println() 是一個方法。
l System 是系統類。
l out 是標準輸出對象。
命令行參數的使用
有時候你但願運行一個程序時候再傳遞給它消息。這要靠傳遞命令行參數給main()函數實現。
命令行參數是在執行程序時候緊跟在程序名字後面的信息。
public class CommandLine { public static void main(String args[]){ for(int i=0; i<args.length; i++){ System.out.println("args[" + i + "]: " + args[i]); } }}$ javac CommandLine.java $ java CommandLine this is a command line 200 -100 args[0]: this args[1]: is args[2]: a args[3]: command args[4]: line args[5]: 200 args[6]: -100
當一個對象被建立時候,構造方法用來初始化該對象。構造方法和它所在類的名字相同,但構造方法沒有返回值。
一般會使用構造方法給一個類的實例變量賦初值,或者執行其它必要的步驟來建立一個完整的對象。
無論你是否自定義構造方法,全部的類都有構造方法,由於Java自動提供了一個默認構造方法,默認構造方法的訪問修改符和類的訪問修改符相同(類爲 public,構造函數也爲 public;類改成 private,構造函數也改成 private)。
一旦你定義了本身的構造方法,默認構造方法就會失效。
JDK 1.5 開始,Java支持傳遞同類型的可變參數給一個方法。
方法的可變參數的聲明以下所示:
typeName... parameterName
在方法聲明中,在指定參數類型後加一個省略號(...) 。
一個方法中只能指定一個可變參數,它必須是方法的最後一個參數。任何普通的參數必須在它以前聲明。
public class VarargsDemo { public static void main(String args[]) { // 調用可變參數的方法 printMax(34, 3, 3, 2, 56.5); printMax(new double[]{1, 2, 3}); } public static void printMax( double... numbers) { if (numbers.length == 0) { System.out.println("No argument passed"); return; } double result = numbers[0]; for (int i = 1; i < numbers.length; i++){ if (numbers[i] > result) { result = numbers[i]; } } System.out.println("The max value is " + result); } }
Java 容許定義這樣的方法,它在對象被垃圾收集器析構(回收)以前調用,這個方法叫作 finalize( ),它用來清除回收對象。
例如,你可使用 finalize() 來確保一個對象打開的文件被關閉了。
在 finalize() 方法裏,你必須指定在對象銷燬時候要執行的操做。
finalize() 通常格式是:
protected void finalize(){ // 在這裏終結代碼}
關鍵字 protected 是一個限定符,它確保 finalize() 方法不會被該類之外的代碼調用。
固然,Java 的內存回收能夠由 JVM 來自動完成。若是你手動使用,則可使用上面的方法。
http://www.runoob.com/java/java-files-io.html
Java 的控制檯輸入由 System.in 完成。
爲了得到一個綁定到控制檯的字符流,你能夠把 System.in 包裝在一個 BufferedReader 對象中來建立一個字符流。
下面是建立 BufferedReader 的基本語法:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader 對象建立後,咱們即可以使用 read() 方法從控制檯讀取一個字符,或者用 readLine() 方法讀取一個字符串。
從 BufferedReader 對象讀取一個字符要使用 read() 方法,它的語法以下:
int read( ) throws IOException
每次調用 read() 方法,它從輸入流讀取一個字符並把該字符做爲整數值返回。 當流結束的時候返回 -1。該方法拋出 IOException。
從標準輸入讀取一個字符串須要使用 BufferedReader 的 readLine() 方法。
它的通常格式是:
String readLine( ) throws IOException
JDK 5 後的版本咱們也可使用 Java Scanner 類來獲取控制檯的輸入。
在此前已經介紹過,控制檯的輸出由 print( ) 和 println() 完成。這些方法都由類 PrintStream 定義,System.out 是該類對象的一個引用。
PrintStream 繼承了 OutputStream類,而且實現了方法 write()。這樣,write() 也能夠用來往控制檯寫操做。
PrintStream 定義 write() 的最簡單格式以下所示:
void write(int byteval)
該方法將 byteval 的低八位字節寫到流中。
注意:write() 方法不常用,由於 print() 和 println() 方法用起來更爲方便。
如前所述,一個流被定義爲一個數據序列。輸入流用於從源讀取數據,輸出流用於向目標寫數據。
該流用於從文件讀取數據,它的對象能夠用關鍵字 new 來建立。
有多種構造方法可用來建立對象。
可使用字符串類型的文件名來建立一個輸入流對象來讀取文件:
InputStream f = new FileInputStream("C:/java/hello");
也可使用一個文件對象來建立一個輸入流對象來讀取文件。咱們首先得使用 File() 方法來建立一個文件對象:
File f = new File("C:/java/hello");InputStream out = new FileInputStream(f);
該類用來建立一個文件並向文件中寫數據。
若是該流在打開文件進行輸出前,目標文件不存在,那麼該流會建立該文件。
有兩個構造方法能夠用來建立 FileOutputStream 對象。
使用字符串類型的文件名來建立一個輸出流對象:
OutputStream f = new FileOutputStream("C:/java/hello")
也可使用一個文件對象來建立一個輸出流來寫文件。咱們首先得使用File()方法來建立一個文件對象:
File f = new File("C:/java/hello"); OutputStream f = new FileOutputStream(f);
還有一些關於文件和I/O的類,咱們也須要知道:
建立目錄:
File類中有兩個方法能夠用來建立文件夾:
l mkdir( )方法建立一個文件夾,成功則返回true,失敗則返回false。失敗代表File對象指定的路徑已經存在,或者因爲整個路徑還不存在,該文件夾不能被建立。
l mkdirs()方法建立一個文件夾和它的全部父文件夾。
注意:linux文件路徑分隔符爲 / ,windows的文件路徑分隔符爲 \ 。 Java 在 UNIX 和 Windows 自動按約定分辨文件路徑分隔符。若是你在 Windows 版本的 Java 中使用分隔符 (/) ,路徑依然可以被正確解析。
一個目錄其實就是一個 File 對象,它包含其餘文件和文件夾。
若是建立一個 File 對象而且它是一個目錄,那麼調用 isDirectory() 方法會返回 true。
能夠經過調用該對象上的 list() 方法,來提取它包含的文件和文件夾的列表。
刪除文件可使用 java.io.File.delete() 方法。
如下代碼會刪除目錄 /tmp/java/,須要注意的是當刪除某一目錄時,必須保證該目錄下沒有其餘文件才能正確刪除,不然將刪除失敗。
java.util.Scanner 是 Java5 的新特徵,咱們能夠經過 Scanner 類來獲取用戶的輸入。
下面是建立 Scanner 對象的基本語法:
Scanner s = new Scanner(System.in);
接下來咱們演示一個最簡單的數據輸入,並經過 Scanner 類的 next() 與 nextLine() 方法獲取輸入的字符串,在讀取前咱們通常須要 使用 hasNext 與 hasNextLine 判斷是否還有輸入的數據
next():
l 一、必定要讀取到有效字符後才能夠結束輸入。
l 二、對輸入有效字符以前遇到的空白,next() 方法會自動將其去掉。
l 三、只有輸入有效字符後纔將其後面輸入的空白做爲分隔符或者結束符。
l next() 不能獲得帶有空格的字符串。
nextLine():
l 一、以Enter爲結束符,也就是說 nextLine()方法返回的是輸入回車以前的全部字符。
l 二、能夠得到空白。
要理解Java異常處理是如何工做的,你須要掌握如下三種類型的異常:
l 檢查性異常:最具表明的檢查性異常是用戶錯誤或問題引發的異常,這是程序員沒法預見的。例如要打開一個不存在文件時,一個異常就發生了,這些異常在編譯時不能被簡單地忽略。
l 運行時異常: 運行時異常是可能被程序員避免的異常。與檢查性異常相反,運行時異常能夠在編譯時被忽略。
l 錯誤: 錯誤不是異常,而是脫離程序員控制的問題。錯誤在代碼中一般被忽略。例如,當棧溢出時,一個錯誤就發生了,它們在編譯也檢查不到的。
全部的異常類是從 java.lang.Exception 類繼承的子類。
Exception 類是 Throwable 類的子類。除了Exception類外,Throwable還有一個子類Error 。
Java 程序一般不捕獲錯誤。錯誤通常發生在嚴重故障時,它們在Java程序處理的範疇以外。
Error 用來指示運行時環境發生的錯誤。
例如,JVM 內存溢出。通常地,程序不會從錯誤中恢復。
異常類有兩個主要的子類:IOException 類和 RuntimeException 類。
在 Java 內置類中(接下來會說明),有大部分經常使用檢查性和非檢查性異常。
Java 語言定義了一些異常類在 java.lang 標準包中。
標準運行時異常類的子類是最多見的異常類。因爲 java.lang 包是默認加載到全部的 Java 程序的,因此大部分從運行時異常類繼承而來的異常均可以直接使用。
Java 根據各個類庫也定義了一些其餘的異常,下面的表中列出了 Java 的非檢查性異常。
下面的列表是 Throwable 類的主要方法:
序號 |
方法及說明 |
1 |
public String getMessage() 返回關於發生的異常的詳細信息。這個消息在Throwable 類的構造函數中初始化了。 |
2 |
public Throwable getCause() 返回一個Throwable 對象表明異常緣由。 |
3 |
public String toString() 使用getMessage()的結果返回類的串級名字。 |
4 |
public void printStackTrace() 打印toString()結果和棧層次到System.err,即錯誤輸出流。 |
5 |
public StackTraceElement [] getStackTrace() 返回一個包含堆棧層次的數組。下標爲0的元素表明棧頂,最後一個元素表明方法調用堆棧的棧底。 |
6 |
public Throwable fillInStackTrace() 用當前的調用棧層次填充Throwable 對象棧層次,添加到棧層次任何先前信息中。 |
注意下面事項:
l catch 不能獨立於 try 存在。
l 在 try/catch 後面添加 finally 塊並不是強制性要求的。
l try 代碼後不能既沒 catch 塊也沒 finally 塊。
l try, catch, finally 塊之間不能添加任何代碼。
在 Java 中你能夠自定義異常。編寫本身的異常類時須要記住下面的幾點。
l 全部異常都必須是 Throwable 的子類。
l 若是但願寫一個檢查性異常類,則須要繼承 Exception 類。
l 若是你想寫一個運行時異常類,那麼須要繼承 RuntimeException 類。
在Java中定義了兩種類型的異常和錯誤。
l JVM(Java虛擬機) 異常:由 JVM 拋出的異常或錯誤。例如:NullPointerException 類,ArrayIndexOutOfBoundsException 類,ClassCastException 類。
l 程序級異常:由程序或者API程序拋出的異常。例如 IllegalArgumentException 類,IllegalStateException 類。
l 子類擁有父類非 private 的屬性、方法。
l 子類能夠擁有本身的屬性和方法,即子類能夠對父類進行擴展。
l 子類能夠用本身的方式實現父類的方法。
l Java 的繼承是單繼承,可是能夠多重繼承,單繼承就是一個子類只能繼承一個父類,多重繼承就是,例如 A 類繼承 B 類,B 類繼承 C 類,因此按照關係就是 C 類是 B 類的父類,B 類是 A 類的父類,這是 Java 繼承區別於 C++ 繼承的一個特性。
l 提升了類之間的耦合性(繼承的缺點,耦合度高就會形成代碼之間的聯繫越緊密,代碼獨立性越差)。
inal關鍵字
final 關鍵字聲明類能夠把類定義爲不能繼承的,即最終類;或者用於修飾方法,該方法不能被子類重寫:
l 聲明類:
final class 類名 {//類體}
l 聲明方法:
修飾符(public/private/default/protected) final 返回值類型 方法名(){//方法體}
注:實例變量也能夠被定義爲 final,被定義爲 final 的變量不能被修改。被聲明爲 final 類的方法自動地聲明爲 final,可是實例變量並非 final
子類是不繼承父類的構造器(構造方法或者構造函數)的,它只是調用(隱式或顯式)。若是父類的構造器帶有參數,則必須在子類的構造器中顯式地經過 super 關鍵字調用父類的構造器並配以適當的參數列表。
若是父類構造器沒有參數,則在子類的構造器中不須要使用 super 關鍵字調用父類構造器,系統會自動調用父類的無參構造器。
重寫是子類對父類的容許訪問的方法的實現過程進行從新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!
重寫的好處在於子類能夠根據須要,定義特定於本身的行爲。 也就是說子類可以根據須要實現父類的方法。
重寫方法不能拋出新的檢查異常或者比被重寫方法申明更加寬泛的異常。例如: 父類的一個方法申明瞭一個檢查異常 IOException,可是在重寫這個方法的時候不能拋出 Exception 異常,由於 Exception 是 IOException 的父類,只能拋出 IOException 的子類異常。
class Animal{ public void move(){ System.out.println("動物能夠移動"); } } class Dog extends Animal{ public void move(){ System.out.println("狗能夠跑和走"); } public void bark(){ System.out.println("狗能夠吠叫"); } } public class TestDog{ public static void main(String args[]){ Animal a = new Animal(); // Animal 對象 Animal b = new Dog(); // Dog 對象 a.move();// 執行 Animal 類的方法 b.move();//執行 Dog 類的方法 b.bark();//報錯 } }
以上實例編譯運行結果以下:
TestDog.java:30: cannot find symbol symbol : method bark() location: class Animal b.bark();
l 參數列表必須徹底與被重寫方法的相同;
l 返回類型必須徹底與被重寫方法的返回類型相同;
l 訪問權限不能比父類中被重寫的方法的訪問權限更低。例如:若是父類的一個方法被聲明爲public,那麼在子類中重寫該方法就不能聲明爲protected。
l 父類的成員方法只能被它的子類重寫。
l 聲明爲final的方法不能被重寫。
l 聲明爲static的方法不能被重寫,可是可以被再次聲明。
l 子類和父類在同一個包中,那麼子類能夠重寫父類全部方法,除了聲明爲private和final的方法。
l 子類和父類不在同一個包中,那麼子類只可以重寫父類的聲明爲public和protected的非final方法。
l 重寫的方法可以拋出任何非強制異常,不管被重寫的方法是否拋出異常。可是,重寫的方法不能拋出新的強制性異常,或者比被重寫方法聲明的更普遍的強制性異常,反之則能夠。
l 構造方法不能被重寫。
l 若是不能繼承一個方法,則不能重寫這個方法。
重載(overloading) 是在一個類裏面,方法名字相同,而參數不一樣。返回類型能夠相同也能夠不一樣。
每一個重載的方法(或者構造函數)都必須有一個獨一無二的參數類型列表。
最經常使用的地方就是構造器的重載。
重載規則:
l 被重載的方法必須改變參數列表(參數個數或類型不同);
l 被重載的方法能夠改變返回類型;
l 被重載的方法能夠改變訪問修飾符;
l 被重載的方法能夠聲明新的或更廣的檢查異常;
l 方法可以在同一個類中或者在一個子類中被重載。
l 沒法以返回值類型做爲重載函數的區分標準。
方法的重寫(Overriding)和重載(Overloading)是java多態性的不一樣表現,重寫是父類與子類之間多態性的一種表現,重載能夠理解成多態的具體表現形式。
l (1)方法重載是一個類中定義了多個方法名相同,而他們的參數的數量不一樣或數量相同而類型和次序不一樣,則稱爲方法的重載(Overloading)。
l (2)方法重寫是在子類存在方法與父類的方法的名字相同,並且參數的個數與類型同樣,返回值也同樣的方法,就稱爲重寫(Overriding)。
l (3)方法重載是一個類的多態性表現,而方法重寫是子類與父類的一種多態性表現。
多態是同一個行爲具備多個不一樣表現形式或形態的能力。
多態就是同一個接口,使用不一樣的實例而執行不一樣操做
多態性是對象多種表現形式的體現。
現實中,好比咱們按下 F1 鍵這個動做:
l 若是當前在 Flash 界面下彈出的就是 AS 3 的幫助文檔;
l 若是當前在 Word 下彈出的就是 Word 幫助;
l 在 Windows 下彈出的就是 Windows 幫助和支持。
同一個事件發生在不一樣的對象上會產生不一樣的結果。
l 繼承
l 重寫
l 父類引用指向子類對象
咱們將介紹在Java中,當設計類時,被重寫的方法的行爲怎樣影響多態性。
咱們已經討論了方法的重寫,也就是子類可以重寫父類的方法。
當子類對象調用重寫的方法時,調用的是子類的方法,而不是父類中被重寫的方法。
要想調用父類中被重寫的方法,則必須使用關鍵字super。
public class Employee{}public class Salary extends Employee{}Salary s = new Salary("員工 A", "北京", 3, 3600.00);Employee e = new Salary("員工 B", "上海", 2, 2400.00);s.mailCheck(); e.mailCheck(); //運行時調用Salary 類中的 mailCheck() 方法。
在編譯的時候,編譯器使用 Employee 類中的 mailCheck() 方法驗證該語句, 可是在運行的時候,Java虛擬機(JVM)調用的是 Salary 類中的 mailCheck() 方法。
Java中全部的方法都能以這種方式表現,所以,重寫的方法能在運行時調用,無論編譯的時候源代碼中引用變量是什麼數據類型。
Java虛方法你能夠理解爲java裏全部被overriding的方法都是virtual的,全部重寫的方法都是override的。
虛方法就是java類在繼承中,在上轉型中,java類對象實際調用的方法是子類重寫的方法;也就是編譯器和jvm調用的不是同一個類的方法;
方式一:重寫:
這個內容已經在上一章節詳細講過,就再也不闡述,詳細可訪問:Java 重寫(Override)與重載(Overload)。
方式二:接口
l 1. 生活中的接口最具表明性的就是插座,例如一個三接頭的插頭都能接在三孔插座中,由於這個是每一個國家都有各自規定的接口規則,有可能到國外就不行,那是由於國外本身定義的接口類型。
l 2. java中的接口相似於生活中的接口,就是一些方法特徵的集合,但沒有方法的實現。具體能夠看 java接口 這一章節的內容。
方式三:抽象類和抽象方法
在面向對象的概念中,全部的對象都是經過類來描繪的,可是反過來,並非全部的類都是用來描繪對象的,若是一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。
抽象類除了不能實例化對象以外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類同樣。
因爲抽象類不能實例化對象,因此抽象類必須被繼承,才能被使用。也是由於這個緣由,一般在設計階段決定要不要設計抽象類。
父類包含了子類集合的常見的方法,可是因爲父類自己是抽象的,因此不能使用這些方法。
在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口。
若是你想設計這樣一個類,該類包含一個特別的成員方法,該方法的具體實現由它的子類肯定,那麼你能夠在父類中聲明該方法爲抽象方法。
Abstract 關鍵字一樣能夠用來聲明抽象方法,抽象方法只包含一個方法名,而沒有方法體。
抽象方法沒有定義,方法名後面直接跟一個分號,而不是花括號。
public abstract double computePay();
聲明抽象方法會形成如下兩個結果:
l 若是一個類包含抽象方法,那麼該類必須是抽象類。
l 任何子類必須重寫父類的抽象方法,或者聲明自身爲抽象類。
繼承抽象方法的子類必須重寫該方法。不然,該子類也必須聲明爲抽象類。最終,必須有子類實現該抽象方法,不然,從最初的父類到最終的子類都不能用來實例化對象。
l 1. 抽象類不能被實例化(初學者很容易犯的錯),若是被實例化,就會報錯,編譯沒法經過。只有抽象類的非抽象子類能夠建立對象。
l 2. 抽象類中不必定包含抽象方法,可是有抽象方法的類一定是抽象類。
l 3. 抽象類中的抽象方法只是聲明,不包含方法體,就是不給出方法的具體實現也就是方法的具體功能。
l 4. 構造方法,類方法(用 static 修飾的方法)不能聲明爲抽象方法。
l 5. 抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類。
在面向對象程式設計方法中,封裝(英語:Encapsulation)是指一種將抽象性函式接口的實現細節部份包裝、隱藏起來的方法。
封裝能夠被認爲是一個保護屏障,防止該類的代碼和數據被外部類定義的代碼隨機訪問。
要訪問該類的代碼和數據,必須經過嚴格的接口控制。
封裝最主要的功能在於咱們能修改本身的實現代碼,而不用修改那些調用咱們代碼的程序片斷。
適當的封裝可讓程式碼更容易理解與維護,也增強了程式碼的安全性。
l 1. 良好的封裝可以減小耦合。
l 2. 類內部的結構能夠自由修改。
l 3. 能夠對成員變量進行更精確的控制。
l 4. 隱藏信息,實現細節。
1. 修改屬性的可見性來限制對屬性的訪問(通常限制爲private)
2. 對每一個值屬性提供對外的公共方法訪問,也就是建立一對賦取值方法,用於對私有屬性的訪問(getter和setter方法)
接口(英文:Interface),在JAVA編程語言中是一個抽象類型,是抽象方法的集合,接口一般以interface來聲明。一個類經過繼承接口的方式,從而來繼承接口的抽象方法。
接口並非類,編寫接口的方式和類很類似,可是它們屬於不一樣的概念。類描述對象的屬性和方法。接口則包含類要實現的方法。
除非實現接口的類是抽象類,不然該類要定義接口中的全部方法。
接口沒法被實例化,可是能夠被實現。一個實現接口的類,必須實現接口內所描述的全部方法,不然就必須聲明爲抽象類。另外,在 Java 中,接口類型可用來聲明一個變量,他們能夠成爲一個空指針,或是被綁定在一個以此接口實現的對象。
l 一個接口能夠有多個方法。
l 接口文件保存在 .java 結尾的文件中,文件名使用接口名。
l 接口的字節碼文件保存在 .class 結尾的文件中。
l 接口相應的字節碼文件必須在與包名稱相匹配的目錄結構中。
l 接口不能用於實例化對象。
l 接口沒有構造方法。
l 接口中全部的方法必須是抽象方法。
l 接口不能包含成員變量,除了 static 和 final 變量。
l 接口不是被類繼承了,而是要被類實現。
l 接口支持多繼承。
l 接口中每個方法也是隱式抽象的,接口中的方法會被隱式的指定爲 public abstract(只能是 public abstract,其餘修飾符都會報錯)。
l 接口中能夠含有變量,可是接口中的變量會被隱式的指定爲 public static final 變量(而且只能是 public,用 private 修飾會報編譯錯誤)。
l 接口中的方法是不能在接口中實現的,只能由實現接口的類來實現接口中的方法。
l 1. 抽象類中的方法能夠有方法體,就是能實現方法的具體功能,可是接口中的方法不行。
l 2. 抽象類中的成員變量能夠是各類類型的,而接口中的成員變量只能是 public static final 類型的。
l 3. 接口中不能含有靜態代碼塊以及靜態方法(用 static 修飾的方法),而抽象類是能夠有靜態代碼塊和靜態方法。
l 4. 一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口。
重寫接口中聲明的方法時,須要注意如下規則:
l 類在實現接口的方法時,不能拋出強制性異常,只能在接口中,或者繼承接口的抽象類中拋出該強制性異常。
l 類在重寫方法時要保持一致的方法名,而且應該保持相同或者相兼容的返回值類型。
l 若是實現接口的類是抽象類,那麼就不必實現該接口的方法。
在實現接口的時候,也要注意一些規則:
l 一個類能夠同時實現多個接口。
l 一個類只能繼承一個類,可是能實現多個接口。
l 一個接口能繼承另外一個接口,這和類之間的繼承比較類似。
在Java中,類的多繼承是不合法,但接口容許多繼承。
在接口的多繼承中extends關鍵字只須要使用一次,在其後跟着繼承接口。 以下所示:
public interface Hockey extends Sports, Event
以上的程序片斷是合法定義的子接口,與類不一樣的是,接口容許多繼承,而 Sports及 Event 可能定義或是繼承相同的方法
最經常使用的繼承接口是沒有包含任何方法的接口。
標記接口是沒有任何方法和屬性的接口.它僅僅代表它的類屬於一個特定的類型,供其餘代碼來測試容許作一些事情。
標記接口做用:簡單形象的說就是給某個對象打個標(蓋個戳),使對象擁有某個或某些特權。
沒有任何方法的接口被稱爲標記接口。標記接口主要用於如下兩種目的:
l 創建一個公共的父接口:
正如EventListener接口,這是由幾十個其餘接口擴展的Java API,你可使用一個標記接口來創建一組接口的父接口。例如:當一個接口繼承了EventListener接口,Java虛擬機(JVM)就知道該接口將要被用於一個事件的代理方案。
l 向一個類添加數據類型:
這種狀況是標記接口最初的目的,實現標記接口的類不須要定義任何接口方法(由於標記接口根本就沒有方法),可是該類經過多態性變成一個接口類型。
爲了更好地組織類,Java 提供了包機制,用於區別類名的命名空間。
l 一、把功能類似或相關的類或接口組織在同一個包中,方便類的查找和使用。
l 二、如同文件夾同樣,包也採用了樹形目錄的存儲方式。同一個包中的類名字是不一樣的,不一樣的包中的類的名字是能夠相同的,當同時調用兩個不一樣包中相同類名的類時,應該加上包名加以區別。所以,包能夠避免名字衝突。
l 三、包也限定了訪問權限,擁有包訪問權限的類才能訪問某個包中的類。
若是在一個包中,一個類想要使用本包中的另外一個類,那麼該包名能夠省略。
注意:類文件中能夠包含任意數量的 import 聲明。import 聲明必須在包聲明以後,類聲明以前。
類放在包中會有兩種主要的結果:
l 包名成爲類名的一部分,正如咱們前面討論的同樣。
l 包名必須與相應的字節碼所在的目錄結構相吻合。
一般,一個公司使用它互聯網域名的顛倒形式來做爲它的包名.例如:互聯網域名是 runoob.com,全部的包名都以 com.runoob 開頭。包名中的每個部分對應一個子目錄。
Java工具包提供了強大的數據結構。在Java中的數據結構主要包括如下幾種接口和類:
l 枚舉(Enumeration)
l 位集合(BitSet)
l 向量(Vector)
l 棧(Stack)
l 字典(Dictionary)
l 哈希表(Hashtable)
l 屬性(Properties)
序號 |
類描述 |
1 |
Vector 該類和ArrayList很是類似,可是該類是同步的,能夠用在多線程的狀況,該類容許設置默認的增加長度,默認擴容方式爲原來的2倍。 |
2 |
Stack 棧是Vector的一個子類,它實現了一個標準的後進先出的棧。 |
3 |
Dictionary Dictionary 類是一個抽象類,用來存儲鍵/值對,做用和Map類類似。 |
4 |
Hashtable Hashtable 是 Dictionary(字典) 類的子類,位於 java.util 包中。 |
5 |
Properties Properties 繼承於 Hashtable,表示一個持久的屬性集,屬性列表中每一個鍵及其對應值都是一個字符串。 |
6 |
BitSet 一個Bitset類建立一種特殊類型的數組來保存位值。BitSet中數組大小會隨須要增長。 |
枚舉(Enumeration)接口雖然它自己不屬於數據結構,但它在其餘數據結構的範疇裏應用很廣。 枚舉(The Enumeration)接口定義了一種從數據結構中取回連續元素的方式。
例如,枚舉定義了一個叫nextElement 的方法,該方法用來獲得一個包含多元素的數據結構的下一個元素。
關於枚舉接口的更多信息,請參見枚舉(Enumeration)。
位集合類實現了一組能夠單獨設置和清除的位或標誌。
該類在處理一組布爾值的時候很是有用,你只須要給每一個值賦值一"位",而後對位進行適當的設置或清除,就能夠對布爾值進行操做了。
關於該類的更多信息,請參見位集合(BitSet)。
向量(Vector)類和傳統數組很是類似,可是Vector的大小能根據須要動態的變化。
和數組同樣,Vector對象的元素也能經過索引訪問。
使用Vector類最主要的好處就是在建立對象的時候沒必要給對象指定大小,它的大小會根據須要動態的變化。
關於該類的更多信息,請參見向量(Vector)
棧(Stack)實現了一個後進先出(LIFO)的數據結構。
你能夠把棧理解爲對象的垂直分佈的棧,當你添加一個新元素時,就將新元素放在其餘元素的頂部。
當你從棧中取元素的時候,就從棧頂取一個元素。換句話說,最後進棧的元素最早被取出。
關於該類的更多信息,請參見棧(Stack)。
堆棧除了包括由Vector定義的全部方法,也定義了本身的一些方法。
序號 |
方法描述 |
1 |
boolean empty() 測試堆棧是否爲空。 |
2 |
Object peek( ) 查看堆棧頂部的對象,但不從堆棧中移除它。 |
3 |
Object pop( ) 移除堆棧頂部的對象,並做爲此函數的值返回該對象。 |
4 |
Object push(Object element) 把項壓入堆棧頂部。 |
5 |
int search(Object element) 返回對象在堆棧中的位置,以 1 爲基數。 |
字典(Dictionary) 類是一個抽象類,它定義了鍵映射到值的數據結構。
當你想要經過特定的鍵而不是整數索引來訪問數據的時候,這時候應該使用Dictionary。
因爲Dictionary類是抽象類,因此它只提供了鍵映射到值的數據結構,而沒有提供特定的實現。
關於該類的更多信息,請參見字典( Dictionary)。
Dictionary類已通過時了。在實際開發中,你能夠實現Map接口來獲取鍵/值的存儲功能。
Hashtable類提供了一種在用戶定義鍵結構的基礎上來組織數據的手段。
例如,在地址列表的哈希表中,你能夠根據郵政編碼做爲鍵來存儲和排序數據,而不是經過人名。
哈希表鍵的具體含義徹底取決於哈希表的使用情景和它包含的數據。
關於該類的更多信息,請參見哈希表(HashTable)。
Hashtable是原始的java.util的一部分, 是一個Dictionary具體的實現 。
然而,Java 2 重構的Hashtable實現了Map接口,所以,Hashtable如今集成到了集合框架中。它和HashMap類很類似,可是它支持同步。
像HashMap同樣,Hashtable在哈希表中存儲鍵/值對。當使用一個哈希表,要指定用做鍵的對象,以及要連接到該鍵的值。
Properties 繼承於 Hashtable.Properties 類表示了一個持久的屬性集.屬性列表中每一個鍵及其對應值都是一個字符串。
Properties 類被許多Java類使用。例如,在獲取環境變量時它就做爲System.getProperties()方法的返回值。
關於該類的更多信息,請參見屬性(Properties)。
Java 中的 Iterator 功能比較簡單,而且只能單向移動:
l (1) 使用方法 iterator() 要求容器返回一個 Iterator。第一次調用 Iterator 的 next() 方法時,它返回序列的第一個元素。注意:iterator() 方法是 java.lang.Iterable 接口,被 Collection 繼承。
l (2) 使用 next() 得到序列中的下一個元素。
l (3) 使用 hasNext() 檢查序列中是否還有元素。
l (4) 使用 remove() 將迭代器新返回的元素刪除。
從上面的集合框架圖能夠看到,Java 集合框架主要包括兩種類型的容器,一種是集合(Collection),存儲一個元素集合,另外一種是圖(Map),存儲鍵/值對映射。Collection 接口又有 3 種子類型,List、Set 和 Queue,再下面是一些抽象類,最後是具體實現類,經常使用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
集合框架是一個用來表明和操縱集合的統一架構。全部的集合框架都包含以下內容:
l 接口:是表明集合的抽象數據類型。例如 Collection、List、Set、Map 等。之因此定義多個接口,是爲了以不一樣的方式操做集合對象
l 實現(類):是集合接口的具體實現。從本質上講,它們是可重複使用的數據結構,例如:ArrayList、LinkedList、HashSet、HashMap。
l 算法:是實現集合接口的對象裏的方法執行的一些有用的計算,例如:搜索和排序。這些算法被稱爲多態,那是由於相同的方法能夠在類似的接口上有着不一樣的實現。
l 1. Set 接口實例存儲的是無序的,不重複的數據。List 接口實例存儲的是有序的,能夠重複的元素。
l 2. Set檢索效率低下,刪除和插入效率高,插入和刪除不會引發元素位置改變 <實現類有HashSet,TreeSet>。
l 3. List和數組相似,能夠動態增加,根據實際存儲的數據的長度自動增加List的長度。查找元素效率高,插入刪除效率低,由於會引發其餘元素位置改變 <實現類有ArrayList,LinkedList,Vector> 。
集合框架定義了幾種算法,可用於集合和映射。這些算法被定義爲集合類的靜態方法。
在嘗試比較不兼容的類型時,一些方法可以拋出 ClassCastException異常。當試圖修改一個不可修改的集合時,拋出UnsupportedOperationException異常。
集合定義三個靜態的變量:EMPTY_SET,EMPTY_LIST,EMPTY_MAP的。這些變量都不可改變。
一般狀況下,你會但願遍歷一個集合中的元素。例如,顯示集合中的每一個元素。
通常遍歷數組都是採用for循環或者加強for,這兩個方法也能夠用在集合框架,可是還有一種方法是採用迭代器遍歷集合框架,它是一個對象,實現了Iterator 接口或ListIterator接口。
迭代器,使你可以經過循環來獲得或刪除集合的元素。ListIterator 繼承了Iterator,以容許雙向遍歷列表和修改元素。
import java.util.*;public class Test{ public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("1", "value1"); map.put("2", "value2"); map.put("3", "value3"); //第一種:廣泛使用,二次取值 System.out.println("經過Map.keySet遍歷key和value:"); for (String key : map.keySet()) { System.out.println("key= "+ key + " and value= " + map.get(key)); } //第二種 System.out.println("經過Map.entrySet使用iterator遍歷key和value:"); Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = it.next(); System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); } //第三種:推薦,尤爲是容量大時 System.out.println("經過Map.entrySet遍歷key和value"); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); } //第四種 System.out.println("經過Map.values()遍歷全部的value,但不能遍歷key"); for (String v : map.values()) { System.out.println("value= " + v); } }}
總結
Java集合框架爲程序員提供了預先包裝的數據結構和算法來操縱他們。
集合是一個對象,可容納其餘對象的引用。集合接口聲明對每一種類型的集合能夠執行的操做。
集合框架的類和接口均在java.util包中。
任何對象加入集合類後,自動轉變爲Object類型,因此在取出的時候,須要進行強制類型轉換。
Java 泛型(generics)是 JDK 5 中引入的一個新特性, 泛型提供了編譯時類型安全檢測機制,該機制容許程序員在編譯時檢測到非法的類型。
泛型的本質是參數化類型,也就是說所操做的數據類型被指定爲一個參數。
假定咱們有這樣一個需求:寫一個排序方法,可以對整型數組、字符串數組甚至其餘任何類型的數組進行排序,該如何實現?
答案是可使用 Java 泛型。
使用 Java 泛型的概念,咱們能夠寫一個泛型方法來對一個對象數組排序。而後,調用該泛型方法來對整型數組、浮點數數組、字符串數組等進行排序。
你能夠寫一個泛型方法,該方法在調用時能夠接收不一樣類型的參數。根據傳遞給泛型方法的參數類型,編譯器適當地處理每個方法調用。
下面是定義泛型方法的規則:
l 全部泛型方法聲明都有一個類型參數聲明部分(由尖括號分隔),該類型參數聲明部分在方法返回類型以前(在下面例子中的<E>)。
l 每個類型參數聲明部分包含一個或多個類型參數,參數間用逗號隔開。一個泛型參數,也被稱爲一個類型變量,是用於指定一個泛型類型名稱的標識符。
l 類型參數能被用來聲明返回值類型,而且能做爲泛型方法獲得的實際參數類型的佔位符。
l 泛型方法體的聲明和其餘方法同樣。注意類型參數只能表明引用型類型,不能是原始類型(像int,double,char的等)。
public static < E > void printArray( E[] inputArray ){} //extends"在通常意義上的意思是"extends"(類)或者"implements"(接口) public static <T extends Comparable<T>> T maximum(T x, T y, T z) {}
泛型類的聲明和非泛型類的聲明相似,除了在類名後面添加了類型參數聲明部分。
和泛型方法同樣,泛型類的類型參數聲明部分也包含一個或多個類型參數,參數間用逗號隔開。一個泛型參數,也被稱爲一個類型變量,是用於指定一個泛型類型名稱的標識符。由於他們接受一個或多個參數,這些類被稱爲參數化的類或參數化的類型。
public class Box<T> {……}
一、類型通配符通常是使用?代替具體的類型參數。例如 List<?> 在邏輯上是List<String>,List<Integer> 等全部List<具體類型實參>的父類。
List<String> name = new ArrayList<String>(); List<Integer> age = new ArrayList<Integer>(); List<Number> number = new ArrayList<Number>(); public static void getData(List<?> data) {……}
解析: 由於getData()方法的參數是List類型的,因此name,age,number均可以做爲這個方法的實參,這就是通配符的做用
二、類型通配符上限經過形如 List<? extends Number>來定義,如此定義就是通配符泛型值接受Number及其下層子類類型。
List<String> name = new ArrayList<String>(); List<Integer> age = new ArrayList<Integer>(); List<Number> number = new ArrayList<Number>(); //getUperNumber(name);//1 getUperNumber(age);//2 getUperNumber(number);//3 public static void getData(List<?> data) {……} public static void getUperNumber(List<? extends Number> data) {……}
解析: 在(//1)處會出現錯誤,由於getUperNumber()方法中的參數已經限定了參數泛型上限爲Number,因此泛型爲String是不在這個範圍以內,因此會報錯
三、類型通配符下限經過形如 List<? super Number>來定義,表示類型只能接受Number及其三層父類類型,如Objec類型的實例。
Java 提供了一種對象序列化的機制,該機制中,一個對象能夠被表示爲一個字節序列,該字節序列包括該對象的數據、有關對象的類型的信息和存儲在對象中數據的類型。
將序列化對象寫入文件以後,能夠從文件中讀取出來,而且對它進行反序列化,也就是說,對象的類型信息、對象的數據,還有對象中的數據類型能夠用來在內存中新建對象。
整個過程都是 Java 虛擬機(JVM)獨立的,也就是說,在一個平臺上序列化的對象能夠在另外一個徹底不一樣的平臺上反序列化該對象。
類 ObjectInputStream 和 ObjectOutputStream 是高層次的數據流,它們包含反序列化和序列化對象的方法。
ObjectOutputStream 類包含不少寫方法來寫各類數據類型,可是一個特別的方法例外:
public final void writeObject(Object x) throws IOException
上面的方法序列化一個對象,並將它發送到輸出流。類似的 ObjectInputStream 類包含以下反序列化一個對象的方法:
public final Object readObject() throws IOException, ClassNotFoundException
該方法從流中取出下一個對象,並將對象反序列化。它的返回值爲Object,所以,你須要將它轉換成合適的數據類型。
請注意,一個類的對象要想序列化成功,必須知足兩個條件:
若是你想知道一個 Java 標準類是不是可序列化的,請查看該類的文檔。檢驗一個類的實例是否能序列化十分簡單, 只須要查看該類有沒有實現 java.io.Serializable接口。
ObjectOutputStream 類用來序列化一個對象,以下的 SerializeDemo 例子實例化了一個 Employee 對象,並將該對象序列化到一個文件中。
該程序執行後,就建立了一個名爲 employee.ser 文件。該程序沒有任何輸出,可是你能夠經過代碼研讀來理解程序的做用。
注意: 當序列化一個對象到文件時, 按照 Java 的標準約定是給文件一個 .ser 擴展名。
Employee e = new Employee(); e.name = "Reyan Ali"; e.address = "Phokka Kuan, Ambehta Peer"; e.SSN = 11122333; e.number = 101; try { FileOutputStream fileOut = new FileOutputStream("/tmp/employee.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(e); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/employee.ser"); }catch(IOException i) { i.printStackTrace(); }
下面的 DeserializeDemo 程序實例了反序列化,/tmp/employee.ser 存儲了 Employee 對象。
Employee e = null; try { FileInputStream fileIn = new FileInputStream("/tmp/employee.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); e = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println("Employee class not found"); c.printStackTrace(); return; }
這裏要注意如下要點:
readObject() 方法中的 try/catch代碼塊嘗試捕獲 ClassNotFoundException 異常。對於 JVM 能夠反序列化對象,它必須是可以找到字節碼的類。若是JVM在反序列化對象的過程當中找不到該類,則拋出一個 ClassNotFoundException 異常。
注意,readObject() 方法的返回值被轉化成 Employee 引用。
當對象被序列化時,屬性 SSN 的值爲 111222333,可是由於該屬性是短暫的,該值沒有被髮送到輸出流。因此反序列化後 Employee 對象的 SSN 屬性爲 0。
public transient int SSN;
java.net 包中提供了兩種常見的網絡協議的支持:
l TCP:TCP 是傳輸控制協議的縮寫,它保障了兩個應用程序之間的可靠通訊。一般用於互聯網協議,被稱 TCP / IP。
l UDP:UDP 是用戶數據報協議的縮寫,一個無鏈接的協議。提供了應用程序之間要發送的數據的數據包。
套接字使用TCP提供了兩臺計算機之間的通訊機制。 客戶端程序建立一個套接字,並嘗試鏈接服務器的套接字。
當鏈接創建時,服務器會建立一個 Socket 對象。客戶端和服務器如今能夠經過對 Socket 對象的寫入和讀取來進行通訊。
java.net.Socket 類表明一個套接字,而且 java.net.ServerSocket 類爲服務器程序提供了一種來監聽客戶端,並與他們創建鏈接的機制。
如下步驟在兩臺計算機之間使用套接字創建TCP鏈接時會出現:
l 服務器實例化一個 ServerSocket 對象,表示經過服務器上的端口通訊。
l 服務器調用 ServerSocket 類的 accept() 方法,該方法將一直等待,直到客戶端鏈接到服務器上給定的端口。
l 服務器正在等待時,一個客戶端實例化一個 Socket 對象,指定服務器名稱和端口號來請求鏈接。
l Socket 類的構造函數試圖將客戶端鏈接到指定的服務器和端口號。若是通訊被創建,則在客戶端建立一個 Socket 對象可以與服務器進行通訊。
l 在服務器端,accept() 方法返回服務器上一個新的 socket 引用,該 socket 鏈接到客戶端的 socket。
鏈接創建後,經過使用 I/O 流在進行通訊,每個socket都有一個輸出流和一個輸入流,客戶端的輸出流鏈接到服務器端的輸入流,而客戶端的輸入流鏈接到服務器端的輸出流。
TCP 是一個雙向的通訊協議,所以數據能夠經過兩個數據流在同一時間發送.如下是一些類提供的一套完整的有用的方法來實現 socket。
服務器應用程序經過使用 java.net.ServerSocket 類以獲取一個端口,而且偵聽客戶端請求。
建立非綁定服務器套接字。 若是 ServerSocket 構造方法沒有拋出異常,就意味着你的應用程序已經成功綁定到指定的端口,而且偵聽客戶端請求。
這裏有一些 ServerSocket 類的經常使用方法:
序號 |
方法描述 |
1 |
public int getLocalPort() 返回此套接字在其上偵聽的端口。 |
2 |
public Socket accept() throws IOException 偵聽並接受到此套接字的鏈接。 |
3 |
public void setSoTimeout(int timeout) 經過指定超時值啓用/禁用 SO_TIMEOUT,以毫秒爲單位。 |
4 |
public void bind(SocketAddress host, int backlog) 將 ServerSocket 綁定到特定地址(IP 地址和端口號)。 |
java.net.Socket 類表明客戶端和服務器都用來互相溝通的套接字。客戶端要獲取一個 Socket 對象經過實例化 ,而 服務器得到一個 Socket 對象則經過 accept() 方法的返回值。
當 Socket 構造方法返回,並無簡單的實例化了一個 Socket 對象,它實際上會嘗試鏈接到指定的服務器和端口。
下面列出了一些感興趣的方法,注意客戶端和服務器端都有一個 Socket 對象,因此不管客戶端仍是服務端都可以調用這些方法。
序號 |
方法描述 |
1 |
public void connect(SocketAddress host, int timeout) throws IOException 將此套接字鏈接到服務器,並指定一個超時值。 |
2 |
public InetAddress getInetAddress() 返回套接字鏈接的地址。 |
3 |
public int getPort() 返回此套接字鏈接到的遠程端口。 |
4 |
public int getLocalPort() 返回此套接字綁定到的本地端口。 |
5 |
public SocketAddress getRemoteSocketAddress() 返回此套接字鏈接的端點的地址,若是未鏈接則返回 null。 |
6 |
public InputStream getInputStream() throws IOException 返回此套接字的輸入流。 |
7 |
public OutputStream getOutputStream() throws IOException 返回此套接字的輸出流。 |
8 |
public void close() throws IOException 關閉此套接字。 |
這個類表示互聯網協議(IP)地址。下面列出了 Socket 編程時比較有用的方法:
序號 |
方法描述 |
1 |
static InetAddress getByAddress(byte[] addr) 在給定原始 IP 地址的狀況下,返回 InetAddress 對象。 |
2 |
static InetAddress getByAddress(String host, byte[] addr) 根據提供的主機名和 IP 地址建立 InetAddress。 |
3 |
static InetAddress getByName(String host) 在給定主機名的狀況下肯定主機的 IP 地址。 |
4 |
String getHostAddress() 返回 IP 地址字符串(以文本表現形式)。 |
5 |
String getHostName() 獲取此 IP 地址的主機名。 |
6 |
static InetAddress getLocalHost() 返回本地主機。 |
7 |
String toString() 將此 IP 地址轉換爲 String。 |
Java 給多線程編程提供了內置的支持。 一條線程指的是進程中一個單一順序的控制流,一個進程中能夠併發多個線程,每條線程並行執行不一樣的任務。
多線程是多任務的一種特別的形式,但多線程使用了更小的資源開銷。
這裏定義和線程相關的另外一個術語 - 進程:一個進程包括由操做系統分配的內存空間,包含一個或多個線程。一個線程不能獨立的存在,它必須是進程的一部分。一個進程一直運行,直到全部的非守護線程都結束運行後才能結束。
多線程能知足程序員編寫高效率的程序來達到充分利用 CPU 的目的。
l 新建狀態:
使用 new 關鍵字和 Thread 類或其子類創建一個線程對象後,該線程對象就處於新建狀態。它保持這個狀態直到程序 start() 這個線程。
l 就緒狀態:
當線程對象調用了start()方法以後,該線程就進入就緒狀態。就緒狀態的線程處於就緒隊列中,要等待JVM裏線程調度器的調度。
l 運行狀態:
若是就緒狀態的線程獲取 CPU 資源,就能夠執行 run(),此時線程便處於運行狀態。處於運行狀態的線程最爲複雜,它能夠變爲阻塞狀態、就緒狀態和死亡狀態。
l 阻塞狀態:
若是一個線程執行了sleep(睡眠)、suspend(掛起)等方法,失去所佔用資源以後,該線程就從運行狀態進入阻塞狀態。在睡眠時間已到或得到設備資源後能夠從新進入就緒狀態。能夠分爲三種:
n 等待阻塞:運行狀態中的線程執行 wait() 方法,使線程進入到等待阻塞狀態。
n 同步阻塞:線程在獲取 synchronized 同步鎖失敗(由於同步鎖被其餘線程佔用)。
n 其餘阻塞:經過調用線程的 sleep() 或 join() 發出了 I/O 請求時,線程就會進入到阻塞狀態。當sleep() 狀態超時,join() 等待線程終止或超時,或者 I/O 處理完畢,線程從新轉入就緒狀態。
l 死亡狀態:
一個運行狀態的線程完成任務或者其餘終止條件發生時,該線程就切換到終止狀態。
每個 Java 線程都有一個優先級,這樣有助於操做系統肯定線程的調度順序。
Java 線程的優先級是一個整數,其取值範圍是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
默認狀況下,每個線程都會分配一個優先級 NORM_PRIORITY(5)。
具備較高優先級的線程對程序更重要,而且應該在低優先級的線程以前分配處理器資源。可是,線程優先級不能保證線程執行的順序,並且很是依賴於平臺。
Java 提供了三種建立線程的方法:
l 經過實現 Runnable 接口;
l 經過繼承 Thread 類自己;
l 經過 Callable 和 Future 建立線程。
建立一個線程,最簡單的方法是建立一個實現 Runnable 接口的類。
爲了實現 Runnable,一個類只須要執行一個方法調用 run(),聲明以下:
public void run()
你能夠重寫該方法,重要的是理解的 run() 能夠調用其餘方法,使用其餘類,並聲明變量,就像主線程同樣。
在建立一個實現 Runnable 接口的類以後,你能夠在類中實例化一個線程對象。
Thread 定義了幾個構造方法,下面的這個是咱們常用的:
Thread(Runnable threadOb,String threadName);
這裏,threadOb 是一個實現 Runnable 接口的類的實例,而且 threadName 指定新線程的名字。
新線程建立以後,你調用它的 start() 方法它纔會運行。
void start();
建立一個線程的第二種方法是建立一個新的類,該類繼承 Thread 類,而後建立一個該類的實例。
繼承類必須重寫 run() 方法,該方法是新線程的入口點。它也必須調用 start() 方法才能執行。
該方法儘管被列爲一種多線程實現方式,可是本質上也是實現了 Runnable 接口的一個實例。
下表列出了Thread類的一些重要方法:
序號 |
方法描述 |
1 |
public void start() 使該線程開始執行;Java 虛擬機調用該線程的 run 方法。 |
2 |
public void run() 若是該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;不然,該方法不執行任何操做並返回。 |
3 |
public final void setName(String name) 改變線程名稱,使之與參數 name 相同。 |
4 |
public final void setPriority(int priority) 更改線程的優先級。 |
5 |
public final void setDaemon(boolean on) 將該線程標記爲守護線程或用戶線程。 |
6 |
public final void join(long millisec) 等待該線程終止的時間最長爲 millis 毫秒。 |
7 |
public void interrupt() 中斷線程。 |
8 |
public final boolean isAlive() 測試線程是否處於活動狀態。 |
l 1. 建立 Callable 接口的實現類,並實現 call() 方法,該 call() 方法將做爲線程執行體,而且有返回值。
l 2. 建立 Callable 實現類的實例,使用 FutureTask 類來包裝 Callable 對象,該 FutureTask 對象封裝了該 Callable 對象的 call() 方法的返回值。
l 3. 使用 FutureTask 對象做爲 Thread 對象的 target 建立並啓動新線程。
l 4. 調用 FutureTask 對象的 get() 方法來得到子線程執行結束後的返回值。
l 1. 採用實現 Runnable、Callable 接口的方式建立多線程時,線程類只是實現了 Runnable 接口或 Callable 接口,還能夠繼承其餘類。
l 2. 使用繼承 Thread 類的方式建立多線程時,編寫簡單,若是須要訪問當前線程,則無需使用 Thread.currentThread() 方法,直接使用 this 便可得到當前線程。
在多線程編程時,你須要瞭解如下幾個概念:
l 線程同步
l 線程間通訊
l 線程死鎖
l 線程控制:掛起、中止和恢復
有效利用多線程的關鍵是理解程序是併發執行而不是串行執行的。例如:程序中有兩個子系統須要併發執行,這時候就須要利用多線程編程。
經過對多線程的使用,能夠編寫出很是高效的程序。不過請注意,若是你建立太多的線程,程序執行的效率其實是下降了,而不是提高了。
請記住,上下文的切換開銷也很重要,若是你建立了太多的線程,CPU 花費在上下文的切換的時間將多於執行程序的時間!
Applet是採用Java編程語言編寫的小應用程序,該程序能夠包含在 HTML(標準通用標記語言的一個應用)頁中,與在頁中包含圖像的方式大體相同。含有Applet的網頁的HTML文件代碼中部帶有<applet> 和</applet>這樣一對標記,當支持Java的網絡瀏覽器遇到這對標記時,就將下載相應的小應用程序代碼並在本地計算機上執行該Applet。
Applet 是一種 Java 程序。它通常運行在支持 Java 的 Web 瀏覽器內。由於它有完整的 Java API支持,因此Applet 是一個全功能的 Java 應用程序。
以下所示是獨立的 Java 應用程序和 applet 程序之間重要的不一樣:
l Java 中 Applet 類繼承了 java.applet.Applet 類。
l Applet 類沒有定義 main(),因此一個 Applet 程序不會調用 main() 方法。
l Applet 被設計爲嵌入在一個 HTML 頁面。
l 當用戶瀏覽包含 Applet 的 HTML 頁面,Applet 的代碼就被下載到用戶的機器上。
l 要查看一個 Applet 須要 JVM。 JVM 能夠是 Web 瀏覽器的一個插件,或一個獨立的運行時環境。
l 用戶機器上的 JVM 建立一個 Applet 類的實例,並調用 Applet 生命週期過程當中的各類方法。
l Applet 有 Web 瀏覽器強制執行的嚴格的安全規則,Applet 的安全機制被稱爲沙箱安全。
l Applet 須要的其餘類能夠用 Java 歸檔(JAR)文件的形式下載下來。
Applet 類中的四個方法給咱們提供了一個框架,你能夠在該框架上開發小程序:
l init: 該方法的目的是爲你的 Applet 提供所需的任何初始化。在 Applet 標記內的 param 標籤被處理後調用該方法。
l start: 瀏覽器調用 init 方法後,該方法被自動調用。每當用戶從其餘頁面返回到包含 Applet 的頁面時,則調用該方法。
l stop: 當用戶從包含 Applet 的頁面移除的時候,該方法自動被調用。所以,能夠在相同的 Applet 中反覆調用該方法。
l destroy: 此方法僅當瀏覽器正常關閉時調用。由於 Applet 只有在 HTML 網頁上有效,因此你不該該在用戶離開包含 Applet 的頁面後遺漏任何資源。
l paint: 該方法在 start() 方法以後當即被調用,或者在 Applet 須要重繪在瀏覽器的時候調用。paint() 方法實際上繼承於 java.awt。
Applet 是一種 Java 程序。它通常運行在支持 Java 的 Web 瀏覽器內。由於它有完整的 Java API 支持,因此 Applet 是一個全功能的 Java 應用程序。
<applet> 標籤是在HTML文件中嵌入 Applet 的基礎。如下是一個調用"Hello World"applet的例子;
<html><title>The Hello, World Applet</title><hr><applet code="HelloWorldApplet.class" width="320" height="120">If your browser was Java-enabled, a "Hello, World" message would appear here.</applet><hr></html>
Java 支持三種註釋方式。前兩種分別是 // 和 /* */,第三種被稱做說明註釋,它以 /** 開始,以 */結束。
說明註釋容許你在程序中嵌入關於程序的信息。你可使用 javadoc 工具軟件來生成信息,並輸出到HTML文件中。
說明註釋,使你更加方便的記錄你的程序信息。
javadoc 工具軟件識別如下標籤:
標籤 |
描述 |
示例 |
@author |
標識一個類的做者 |
@author description |
@deprecated |
指名一個過時的類或成員 |
@deprecated description |
@param |
說明一個方法的參數 |
@param parameter-name explanation |
@return |
說明返回值類型 |
@return explanation |
@version |
指定類的版本 |
@version info |
在開始的 /** 以後,第一行或幾行是關於類、變量和方法的主要描述。
以後,你能夠包含一個或多個何種各樣的 @ 標籤。每個 @ 標籤必須在一個新行的開始或者在一行的開始緊跟星號(*).
多個相同類型的標籤應該放成一組。例如,若是你有三個 @see 標籤,能夠將它們一個接一個的放在一塊兒。
下面是一個類的說明註釋的實例:
/*** 這個類繪製一個條形圖 * @author runoob * @version 1.2 */
javadoc 工具將你 Java 程序的源代碼做爲輸入,輸出一些包含你程序註釋的HTML文件。
每個類的信息將在獨自的HTML文件裏。javadoc 也能夠輸出繼承的樹形結構和索引。
因爲 javadoc 的實現不一樣,工做也可能不一樣,你須要檢查你的 Java 開發系統的版本等細節,選擇合適的 Javadoc 版本。
實例
下面是一個使用說明註釋的簡單實例。注意每個註釋都在它描述的項目的前面。
在通過 javadoc 處理以後,SquareNum 類的註釋將在 SquareNum.html 中找到。
import java.io.*;/** * 這個類演示了文檔註釋 * @author Ayan Amhed * @version 1.2 */public class SquareNum { /** * This method returns the square of num. * This is a multiline description. You can use * as many lines as you like. * @param num The value to be squared. * @return num squared. */ public double square(double num) { return num * num; } /** * This method inputs a number from the user. * @return The value input as a double. * @exception IOException On input error. * @see IOException */ public double getNumber() throws IOException { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader inData = new BufferedReader(isr); String str; str = inData.readLine(); return (new Double(str)).doubleValue(); } /** * This method demonstrates square(). * @param args Unused. * @return Nothing. * @exception IOException On input error. * @see IOException */ public static void main(String args[]) throws IOException { SquareNum ob = new SquareNum(); double val; System.out.println("Enter value to be squared: "); val = ob.getNumber(); val = ob.square(val); System.out.println("Squared value is " + val); }}
http://www.runoob.com/java/java-examples.html
http://www.runoob.com/java/java8-new-features.html
Java8 新增了很是多的特性,咱們主要討論如下幾個:
l Lambda 表達式 − Lambda容許把函數做爲一個方法的參數(函數做爲參數傳遞進方法中。
l 方法引用 − 方法引用提供了很是有用的語法,能夠直接引用已有Java類或對象(實例)的方法或構造器。與lambda聯合使用,方法引用可使語言的構造更緊湊簡潔,減小冗餘代碼。
l 默認方法 − 默認方法就是一個在接口裏面有了一個實現的方法。
l 新工具 − 新的編譯工具,如:Nashorn引擎 jjs、 類依賴分析器jdeps。
l Stream API −新添加的Stream API(java.util.stream) 把真正的函數式編程風格引入到Java中。
l Date Time API − 增強對日期與時間的處理。
l Optional 類 − Optional 類已經成爲 Java 8 類庫的一部分,用來解決空指針異常。
l Nashorn, JavaScript 引擎 − Java 8提供了一個新的Nashorn javascript引擎,它容許咱們在JVM上運行特定的javascript應用。
更多的新特性能夠參閱官網:What's New in JDK 8
CREATE TABLE `websites` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(20) NOT NULL DEFAULT '' COMMENT '站點名稱', `url` varchar(255) NOT NULL DEFAULT '', `alexa` int(11) NOT NULL DEFAULT '0' COMMENT 'Alexa 排名', `country` char(10) NOT NULL DEFAULT '' COMMENT '國家', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dalong?Unicode=true&characterEncoding=UTF-8", "root", "admin");
http://www.runoob.com/java/java9-new-features.html
l 模塊系統:模塊是一個包的容器,Java 9 最大的變化之一是引入了模塊系統(Jigsaw 項目)。
l REPL (JShell):交互式編程環境。
l HTTP 2 客戶端:HTTP/2標準是HTTP協議的最新版本,新的 HTTPClient API 支持 WebSocket 和 HTTP2 流以及服務器推送特性。
l 改進的 Javadoc:Javadoc 如今支持在 API 文檔中的進行搜索。另外,Javadoc 的輸出如今符合兼容 HTML5 標準。
l 多版本兼容 JAR 包:多版本兼容 JAR 功能能讓你建立僅在特定版本的 Java 環境中運行庫程序時選擇使用的 class 版本。
l 集合工廠方法:List,Set 和 Map 接口中,新的靜態工廠方法能夠建立這些集合的不可變實例。
l 私有接口方法:在接口中使用private私有方法。咱們可使用 private 訪問修飾符在接口中編寫私有方法。
l 進程 API: 改進的 API 來控制和管理操做系統進程。引進 java.lang.ProcessHandle 及其嵌套接口 Info 來讓開發者逃離時常由於要獲取一個本地進程的 PID 而不得不使用本地代碼的窘境。
l 改進的 Stream API:改進的 Stream API 添加了一些便利的方法,使流處理更容易,並使用收集器編寫複雜的查詢。
l 改進 try-with-resources:若是你已經有一個資源是 final 或等效於 final 變量,您能夠在 try-with-resources 語句中使用該變量,而無需在 try-with-resources 語句中聲明一個新變量。
l 改進的棄用註解 @Deprecated:註解 @Deprecated 能夠標記 Java API 狀態,能夠表示被標記的 API 將會被移除,或者已經破壞。
l 改進鑽石操做符(Diamond Operator) :匿名類可使用鑽石操做符(Diamond Operator)。
l 改進 Optional 類:java.util.Optional 添加了不少新的有用方法,Optional 能夠直接轉爲 stream。
l 多分辨率圖像 API:定義多分辨率圖像API,開發者能夠很容易的操做和展現不一樣分辨率的圖像了。
l 改進的 CompletableFuture API : CompletableFuture 類的異步機制能夠在 ProcessHandle.onExit 方法退出時執行操做。
l 輕量級的 JSON API:內置了一個輕量級的JSON API
l 響應式流(Reactive Streams) API: Java 9中引入了新的響應式流 API 來支持 Java 9 中的響應式編程。
更多的新特性能夠參閱官網:What's New in JDK 9