
Java語言規範、API、JDK、IDE的含義:
Java語言規範是Java文法和語義技術性定義,API是應用程式接口(Java預定義類和接口),Java開發工具包(JDK)包含軟體庫、編譯器、解釋器以及其他工具,內建開發環境(IDE)提供編輯、編譯、調試和線上幫助功能。
Java平台版本:
- Java SE:允許開發和部署在桌面、伺服器和嵌入式環境和實時環境中使用的Java應用程式。
- Java EE:它幫助開發和部署可移植、健壯、可伸縮且安全的伺服器端Java應用程式。Java EE是在Java SE的基礎上建構的,它提供web服務、元件模型、管理和通信API。
- Java ME:它為在移動裝置和嵌入式裝置上運作的應用程式提供一個健壯且靈活的環境。
Java運作環境
Java的目标代碼可以在任何平台上運作,Java的源代碼編譯之後生成.class檔案,由位元組碼構成(比如部落格之前安卓逆向研究的Dalvik位元組碼)。位元組碼可以在任何裝有Java虛拟機的計算機上運作,Java虛拟機是一個用于解釋位元組碼的軟體。
Java程式剖析:
- 注釋:Java程式包含三種注釋,即多行注釋、單行注釋、文檔注釋,多行注釋,
- 修飾符:常見如public, protected, private, static, abstract, final,用于指定資料、方法、類的屬性以及它們的用法。
- 類:是Java的基本結構,一個程式可以包含一個或多個類,一個Java源檔案裡最多隻有一個公有類。
- main方法:Java解釋器通過調用main方法執行應用程式。
常量:
- 一旦初始化後就不能再改變的資料,文法為final datatype CONSTANT_NAME = value;
Java資料類型
-
Java資料類型:包括基本類型和引用類型,
基本類型包括 整數類型(byte, short, int, long) 字元類型(char)浮點類型(float, double)邏輯類型(boolean);
引用類型包括 類,接口,數組。
其中,浮點數中以d或D結尾或者無字尾表示double類型,以f或F結尾的表示float類型;整數字面值中以l或L結尾的表示long類型,其他表示int類型。
-
Java數值類型轉換:
如果有一個操作數是double類型,另一個操作數轉換為double 類型;否則,如果有一個操作數是float類型,另一個操作數轉換為float類型;否則,如果有一個操作數是long類型,另一個操作數轉換為long類型;否則,兩個操作數都轉換為int類型;資料轉換總是向較大範圍的資料類型轉換,避免精度損失。将值指派給較大取值範圍的變量時,自動進行類型轉換;将值指派給較小取值範圍的變量時,必須使用強制類型轉換。
- 字元資料類型:char表示16位的單個Unicode字元,char類型的字面值 包括以兩個單引号界定的單個Unicode字元,可以用甥硸硸形式表示的, 轉義字元表示 b f ` " 。
程式設計風格:
良好的程式設計風格有利于減少錯誤,産生容易閱讀、易于了解的代碼。類和方法前使用文檔注釋,方法步驟前使用行注釋;變量和方法名使用小寫,如果有多個單詞,第一個單詞首字母小寫,其他單詞首字母大寫;類名的每個單詞的首字母大寫;常量使用大寫,單詞間以下劃線分割。
Java常見錯誤類型:
包括文法錯誤,即在編譯期間産生的錯誤;運作時錯誤,導緻程式非正常終止的錯誤;邏輯錯誤,程式不能按預期的方式執行,編譯不會報錯。
條件語句:
包括If語句、switch語句、條件表達式,其中的if語句判斷條件必須是boolean類型的;在if-else條件語句中,else語句與同一塊中最近的if語句比對。在使用條件語句中,避免在條件表達式中使用比較操作符判斷布爾變量的真假。switch語句的判斷條件expression的計算結果隻能是byte, char, short, int。value1-valueN必須與 判斷條件類型相同,且為常量表達式,不能是變量。
Java中常用的數學函數:
-
Math.random方法生成[0.0,1.0)之間的double類型的随機數,可以用它寫出簡單的表達式來生成任意範圍的随機數,一般地,a + (int)(Math.random() * b)傳回[a, a+b);還可以用該方法生成随機字元,Java中每個字元對應一個Unicode編碼從0000到FFFF,在生成一個随機字元,就是産生一個0到65535之間的随機數,是以計算的表達式為(int)(Math.random() * (65535+1))。生成任意2個字元ch 1和ch2(ch1 < ch2)之間的随機字元,
(char)(ch1 + (int)(Math.random() * (ch2 - ch1 + 1)))
字元資料類型和操作
- 在字元型資料和數值類型資料之間轉換時,如果轉換結果适用于目标變量(不會有精度損失),可以采用隐式轉換;否則必須使用強制類型轉換。
- 所有數值運算符都可以用在char型操作數上,如果另一個操作數是數值或字元,那麼char型操作數就自動轉換為數值;如果另一個操作數是字元串,那麼char型操作數就會自動轉換成字元串再和另外一個操作數字元串相連。
字元串類型
String類型是不可變的,其内容是不可修改的;如以下代碼片段:
String s = "java";s = "HTML";12
其中s可以了解為一個對象指針,其指向對象空間,其中的字元串為java,第二句指派隻是将s指向了另一個對象空間。
- equals方法用于比較兩個字元串是否包含相同的内容。
- equalsIngoreCase忽略大小寫比較内容是否相同。
- regionMatch比較部分内容是否相同。
- startsWith判斷是否以某個字元串開始。
- endsWith判斷是否以某個字元串結束。
- compareTo方法用于比較兩個字元串的大小,即第一個不同字元的內插補點.
- 調用length()方法可以擷取字元串的長度。。
- charAt(index)方法可以擷取指定位置的字元,index必須位于0到s.length()-1之間。
- concat()方法用于連接配接兩個字元串,連接配接操作傳回一個新的字元串。
- indexOf傳回字元串中字元或字元串比對的位置,傳回-1表示未找到。indexOf指定第二個參數表示從指定的位置開始查找。
-
toCharArray将字元串轉換成字元數組。valueOf方法将基本資料類型轉換為字元串,例如轉化為字元串,如
String s1 = String.valueOf(1.0); String s2 = String.valueOf(true);;字元串轉換為基本資料類型,Double.parseDouble(str)等。
方法:
- 方法簽名指方法名稱、參數類型、參數數量和傳回類型;==一個類中不能包含簽名相同或僅傳回類型不同的多個方法;==方法頭中聲明的變量稱為形參,**形參可以使用final修飾,表示方法内部不允許修改該參數;**形參不允許有預設值,最後一個可為變長參數。方法可以有傳回值,構造函數沒有傳回值。
- 如果方法聲明中含有形參,調用方法時必須提供實參,實參的類型必須與形參的類型相容:如父類形參可用子類實參。
- 調用方法時,基本資料類型的實參值的副本被傳遞給方法的形參,方法内部對形參的修改不影響實參值;對象類型的參數是引用調用。
方法重載:
- 方法重載是指方法名稱相同,但方法簽名不同的方法,僅傳回類型不同不可重載。一個類中可以包含多個重載的方法。
- 當調用方法時,Java編譯器會根據實參的個數和類型尋找最準确的方法進行調用;調用時比對的方法多于一個,則會産生編譯錯誤,成為歧義調用。
數組:
- 數組是引用類型。
- 多元數組隻是數組的數組,故數組元素也可能是引用類型變量
- 凡使用new後,記憶體單元都初始化為0或Null。
- 聲明數組引用變量,datatype[] arrayRefVar;,任何執行個體化的數組都是Object的子類。
- 數組變量是引用類型的變量,聲明數組變量并不配置設定記憶體空間,必須通過new執行個體化來配置設定記憶體空間。
- 新建立的數組其元素根據類型被初始化為預設的初始值,數值類型為0字元類型為’ ’布爾類型為false引用類型為null
- 數組可以在聲明的括号後提供初始值,double[] mylist = {1.9, 2.9, 3, 3.5};或者double[] mylist = new double[]{1.9, 2.9, 3, 3.5};
- 數組的大小在建立這個數組之後不能被改變,arrayRefVar.length可以通路數組的長度。
- 直接使用指派語句不能實作數組複制,結果是兩個數組引用變量指向同一個數組對象。在将數組作為實參傳遞給方法時,修改形參引用的數組,将改變實參引用的數組。
- JVM将數組存儲在叫堆的記憶體區域裡,數組引用存儲在棧空間中。
- String傳遞給方法:由于實參的字元序列不可修改,将克隆給形參。
- 可以把類型相同,但個數可變的參數傳遞給方法,方法中的參數聲明為typeName…parameterName,==Java将可變長參數當數組看待,通過length屬性得到可變參數的個數。
print(String...args){//可看作String[] argsfor(String temp: args)System.out.println(temp);System.out.println(args.length);}12345
- java.util.Arrays類包括各種靜态方法,其中實作了數組的排序和查找,即sort方法與binarySearch方法。
- 二維數組的每個元素(數組)的長度可以不同,建立二維不規則數組時,可以隻指定第一維下标,第一維的每個元素為null, 必須為每個元素使用new建立數組。
面向對象思考:
- 類間的關系描述方法,關聯關系:是一種通用的二進制關系,對象間通過活動發生聯系,例如學生選學課程,教師教授課程。==在Java中,關聯關系可以用資料域或方法來實作,對于方法,一個類中的方法包含另一個類作為參數。
- 聚合關系是一種擁有關系,表示整體與部分之間的關系,即Has-a的關系,在聚合關系中,一個對象可以被多個聚集着擁有; 組合關系是一種隸屬關系,一個從屬者隻能被一個聚集着擁有。如一個Name對象隻能為一個Person所擁有,但一個Address對象可以被多個Person所共享。
- 繼承關系,表示子類與父類之間的is-a關系,通過繼承,子類可以重用父類的資料和代碼。
- 實作關系,表示接口和類之間的關系,類實作接口。
繼承:
繼承是一種軟體重用,如果沒有繼承,會出現很多重複定義。文法為:
class ClassName extends Superclass{classbody}123
子類繼承了父類中可通路的資料域和方法,子類也可添加新的資料域和方法,子類不繼承符類的構造函數。一個子類隻能有一個直接父類:單繼承。子類繼承的父類的私有屬性不能通路,但是可以通過所繼承的get和set公有方法設定和通路。
-
當第一次建立子類對象時,首先初始化其父類靜态成員變量(如果沒有父類對象),然後初始化目前子類對象的靜态成員變量。注意:第一次之後建立子類對象時,不會再次初始化父類和子類的靜态成員變量。其實,靜态成員變量在有任何執行個體變量對象之前已經存在。
接着執行該子類對象的父類的構造函數super(…),可能是編譯為父類提供的預設無參構造函數super()。然後執行子類執行個體變量定義時的初始化表達式,若定義時未給出初始值,則預設為0或null.最後執行子類構造函數中super(…)後面的語句。
- super關鍵字:super調用父類的構造函數,必須是子類構造函數的第一條且僅一條語句(先構造父類),如果子類構造函數中沒有顯示地調用父類的構造函數,那麼将自動調用父類不帶參數的構造函數。 如果父類屬性或方法可以在子類通路,則使用super.data或者super.method(parameters)進行通路。
- super與無參構造函數:如果一個類自定義了構造函數(不管有無參數),系統不會自動加上無參構造函數; 反之,如果沒定義則會加上。編譯在為子類添加無參構造函數時,用super()預設調用父類的無參構造函數,如果找不到父類的無參構造函數,則子類添加無參構造函數失敗。 是以,如果一個類定義了帶參數的構造函數,一定别忘了定義一個無參構造函數。
執行個體方法覆寫
- 如果子類重新定義了從父類中繼承的執行個體方法,稱為方法覆寫。
- 僅當方法是**可通路的執行個體方法**時,才能被覆寫,即私有執行個體方法不能被覆寫,私有方法自動視為final. (final修飾類時表示其不可被繼承;修飾方法表示不可在子類中被重寫;修飾成員變量時表示隻能在聲明處或者構造函數中初始化一次)。
- 靜态方法不能被覆寫,如果靜态方法在子類中重新定義,那麼父類方法将被隐藏。
- 一旦父類中的方法被覆寫,則不能通過引用的子類對象通路被覆寫的父類方法。在子類類體函數中可以使用super引用被覆寫的父類方法。
- 隐藏和覆寫的差別:覆寫,子類對象被父類引用變量引用,父類引用變量調用的相同簽名的函數是子類函數(不能發現父類函數,晚期綁定);隐藏,同上,但父類引用變量通路的是父類變量、函數(可以在發現)。
- 子類方法同樣可以與父類中可通路的方法構成重載。
多态和動态綁定:
重載發生在編譯時,編譯時編譯器根據方法簽名找到最合适的方法;多态發生在運作時,運作時JVM根據變量所引用的對象的真正類型來找到最合适的執行個體方法。多态是晚期綁定,綁定是指找到函數的入口位址的過程。
通路控制符和修飾符final
成員修飾符本類本包子類它包publicyyyyprotectedyyyn無(package)yynnprivateynnn
- 父類私有成員在子類不可見;
- 父類公有和保護成員在子類可見
- 繼承到子類後不改變父類成員的通路權限。
異常處理:
- 一般而言,帶有異常處理的程式會寫成try…catch的形式;在try體内完成程式的正常處理流程,在catch體内完成異常處理。
- 若正常的異常處理出現錯誤,則使用"throw "抛出異常;抛出的異常由catch捕獲,未被捕獲的異常逐層傳播到main,如果main也沒有處理該異常,則作業系統會終止main執行。
- 抛出而未捕獲(未處理)異常的函數,必須用throws聲明其未處理的這些異常。有些異常是系統抛出的,程式隻需要捕獲處理即可。
-
異常的捕獲順序:無論何時,throw以後的語句都不會執行;無論同層catch是否捕獲、處理本層的異常(即使抛出或轉發異常),同層的finally總是都會執行。 一個catch捕獲到異常後,同層catch都不會執行,然後執行同層finally; 一個同層try-catch-finally結束,若無異常則執行其後語句,若有異常,則跳過其後語句,進入上層catch流程。
上圖中紅色标出的為div的執行軌迹。
自定義異常類:
自定義異常類必須繼承Throwable或其子類;自定義異常類通常繼承Exception及其子類,因為它是程式可處理的類。自定義異常類會在父類的基礎上增加成員變量,是以,通常需要覆寫toString函數(經常被列印)。未增加新成員就沒有必要自定義異常類。自定義異常類通常不必定義clone, equals:捕獲和處理異常時通常隻是引用異常對象而已。
抽象類:
- Java可定義不含方法體的方法,其方法體由子類根據具體情況實作,這樣的方法稱為抽象方法,包括抽象方法的類必須是抽象類。抽象類和抽象方法的聲明必須加上abstract關鍵字。
- 類C如果滿足下面任一條件,則該類包含抽象方法且是抽象類:類C顯示地進行一個抽象方法的聲明;類C的父類中聲明的抽象方法未在類C和它的父類中實作;類C的接口中聲明一個方法,并且類C未實作該方法;隻有類C有一個為實作的方法,類C就是抽象類。
- 抽象類不能被執行個體化,即不能用new關鍵字建立對象;抽象類可以定義構造函數,可以被子類調用;具體子類必須實作抽象父類中所有抽象方法,否則子類需要聲明為抽象類;抽象類隻能用具體子類的對象執行個體化。
接口:
接口是公共靜态常量,公共靜态方法和公共抽象方法,預設執行個體方法的集合。接口中的一切都預設是public的,沒有修飾符的方法預設是abstract的,資料成員預設是static的。
接口不能定義構造函數,一個接口可繼承extends多個接口,接口不能被類extends,一個類可實作implements多個接口。
public interface I1{public static final int k = 1;public abstract void m();}1234
等價于:
public interface I1{int k = 1;//=1不可省略,因為預設是public static final的,必須初始化void m();//不可定義函數體,預設是public abstract.}1234
接口中的方法通過“接口類型的引用變量.方法名”調用,但接口類型的引用變量必須引用實作了該接口的具體類的執行個體對象。接口中的常量名通過"接口名.常量名"通路。