- 面向對象概述
- 面向對象的概念
- 面向對象是相對面向過程而言的。
- 面向過程:
- 強調的是功能行爲。
- 面向對象:
- 將功能封裝進對象,強調具備了功能的對象。
- 面向對象是基於面向過程的。
- 面向對象的特點
- 是一種符合人們思考習慣的思想,可以將複雜的事情簡單化,將程序員從執行者轉換成了指揮者。
- 完成需求時:
- 先要去找具有所需的功能的對象來用。
- 如果該對象不存在,那麼創建一個具有所需功能的對象。
- 這樣簡化開發並提高複用。
- 先要去找具有所需的功能的對象來用。
- 開發的過程:
- 其實就是不斷的創建對象,使用對象, 指揮對象做事情。
- 設計的過程:
- 其實就是在管理和維護對象之間的關 系。
- 面向對象的特徵:
- 封裝(encapsulation)
- 繼承(inheritance)
- 多態(polymorphism)
- 封裝(encapsulation)
- 是一種符合人們思考習慣的思想,可以將複雜的事情簡單化,將程序員從執行者轉換成了指揮者。
- 類與對象的關係
- 類與對象的關係概述
- 類就是對現實生活中事物的描述。
- 對象即是該類事物實實在在存在的個體。
- 類與對象的關係如圖:
圖紙就是類
汽車就是堆內存中的對象
- 類的定義
- Java中用類class來描述事物。
- 屬性:對應類中的成員變量。
- 行爲:對應類中的成員函數。
- 屬性:對應類中的成員變量。
- Java中用類class來描述事物。
- 對象在內存中的結構
- 成員變量和局部變量
- 成員變量
- 成員變量定義在類中,在整個類中都可以被訪問。
- 成員變量隨着對象的建立而建立,存在於對象所在的堆內存中。
- 成員變量有默認初始化值。
- 成員變量定義在類中,在整個類中都可以被訪問。
- 局部變量
- 局部變量只定義在局部範圍內,如:函數內,語句內等。
- 局部變量存在於棧內存中。
- 作用的範圍結束,變量空間會自動釋放。
- 局部變量沒有默認初始化值。
- 局部變量只定義在局部範圍內,如:函數內,語句內等。
- 使用匿名對象的兩種情況
- 當對對象方法僅進行一次調用的時
- 匿名對象可以作爲實際參數進行傳遞
- 封裝(Encapsulation)
- 概念
- 封裝:是指隱藏對象的屬性和實現細節,僅對外提供 公共訪問方式。
- 封裝:是指隱藏對象的屬性和實現細節,僅對外提供 公共訪問方式。
- 好處
- 將變化隔離。
- 便於使用。
- 提高重用性。
- 提高安全性。
- 將變化隔離。
- 封裝原則
- 將不需要對外提供的內容都隱藏起來。
- 把屬性都隱藏,提供公共方法對其訪問。
- 將不需要對外提供的內容都隱藏起來。
- 函數是代碼中最小的封裝。
- private(私有)關鍵字
- 用於修飾成員(成員變量和成員函數)。
- 被私有化的成員只在本類中有效。
- 開發中通常將成員變量私有化,再對外提供對應的set ,get 方法對其進行訪問,以提高對數據訪問的安全性。
- 私有僅僅是封裝的一種表現形式。只要是程序訪問不到的都是封裝的表現。
- 用於修飾成員(成員變量和成員函數)。
- 構造函數
- 構造函數的特點
- 函數名與類名相同。
- 不用定義返回值類型。與void不同,void也是一種返回類型。
- 不可以寫return語句。
- 函數名與類名相同。
- 構造函數的作用
- 對象一建立就會調用與之對應的構造函數。構造函數用於給對象進行初始化。
- 構造函數的其它細節
- 當一個類中沒有定義構造函數時,系統會默認給該類加入一個空參數的構造函數。
- 當在類中自定義了構造函數後,默認的構造函數就沒有了。
- 多個構造函數是以重載的形式存在的。
- 構造函數和一般函數的比較:
- 構造函數在對象一建立時就運行,給對象初始化。
- 一般函數在對象調用時才執行,給對象添加對象具備的功能。
- 一個對象建立,構造函數只運行一次,而一般函數可以被該對象調用多次。
- 構造代碼塊
- 也用於給對象進行初始化。
- 對象一建立就運行,且優先於構造函數執行。
- 構造代碼塊中定義的是不同對象共性的初始化內容,是給所有對象進行統一初始化。而構造函數是給對應的對象進行初始化。
- this關鍵字
- 概述
- this代表其所在函數所屬對象的引用。
- 用途
- 當在函數內需要用到調用該函數的對象時,就用this。例如用於區分同名的成員變量和局部變量。
- this語句可以用於構造函數之間的相互調用。this語句只能定義在構造函數的第一行,即先進行this語句的初始化。
- static(靜態)關鍵字
- 概述
- static只能修飾成員(成員變量,成員方法),不能修飾局部變量。
- 當成員被static修飾後,就多了一個調用方式,除了可以被對象調用外,還可以直接被類名調用:類名.靜態成員
- 靜態成員存放在內存的方法區中。
- 非靜態成員變量也叫實例變量,靜態成員變量也叫類變量。
- 主函數就是靜態函數裏面實例化類的對象後再調用非靜態成員函數的例子。
- static特點:
- 隨着類的加載而加載,隨着類的消失而消失。
- 優先於對象存在。
- 被所有對象所共享。
- 可以直接被類名調用。
- 隨着類的加載而加載,隨着類的消失而消失。
- static只能修飾成員(成員變量,成員方法),不能修飾局部變量。
- 實例變量與類變量的比較
- 存放位置:
- 類變量隨着類的加載而存在於方法區中。
- 實例變量隨着對象的建立而存在於堆內存中。
- 生命週期
- 類變量生命週期最長,隨着類的消失而消失。
- 實例變量生命週期隨着對象的消失而消失。
- static的注意事項
- 靜態方法只能訪問靜態成員。
非靜態方法既可以訪問靜態成員也可以訪問非靜態成員。 - 靜態方法中不可以寫this,super關鍵字。因爲靜態優先於對象存在。
- 靜態方法只能訪問靜態成員。
- static的優缺點
- 好處:
- 對對象的共享數據進行單獨空間的存儲,節省空間。
- 可以直接被類名調用。
- 弊端:
- 生命週期過長。
- 只能訪問靜態成員,訪問具有侷限性。
- 好處:
- main函數
- 主函數是一個特殊的函數,作爲程序的入口,是固定格式的,可以被JVM調用。
- 主函數的定義:public static void main(String[] args)
- public:代表該函數的訪問權限是最大的。
- static:代表主函數隨着類的加載就已經存在了。
- void:主函數沒有具體的返回值。
- mian:不是關鍵字,但是是一個特殊的單詞,可以被JVM識別。
- String[] args:主函數的參數,參數類型是一個字符串類型的數組。
- JVM在調用主函數時,默認傳入的參數是new String[0],也可以給主函數傳入其它參數。
- static的使用時機
- 靜態變量:
- 如果在定義一個類的時候,發現一個成員變量需要被所有實例所共享,那麼這個成員變量就需要定義爲static的。
- 如果在定義一個類的時候,發現一個成員變量需要被所有實例所共享,那麼這個成員變量就需要定義爲static的。
- 靜態方法:
- 如果一個方法不用訪問對象的非靜態成員,那麼就可以定義爲靜態的,這樣使用者就不需要創建對象,直接用類名調用。
- 靜態方法通常是作爲工具方法或者一個可以產生對象的方法被聲明,目的是爲了讓調用者更方便的使用,不必創建對象。
- 如果一個方法不用訪問對象的非靜態成員,那麼就可以定義爲靜態的,這樣使用者就不需要創建對象,直接用類名調用。
- 靜態變量:
- 靜態的應用-工具類
- 工具類裏的方法並沒有使用到類的成員變量,所以類的方法都可以定義爲靜態的。
- 防止用戶創建對象的做法:構造函數私有化
- 幫助文檔的製作javadoc
- 使用文檔註釋修飾一個類的源代碼之後可以通過javadoc.exe來生成幫助文檔。
- 生成文檔的命令:
- javadoc -d (目錄) -version –author (源文件)
- javadoc -d (目錄) -version –author (源文件)
- 批註參數來標記一些特殊的屬性及其相應的說明:
- @author<作者姓名>
- @version<版本信息>
- @param<參數名稱><參數說明>
- @return<返回值說明>
- @author<作者姓名>
- 舉例:
- javadoc -d mydoc -author -version MyDemo.java
- 靜態代碼塊
- 格式:
- 靜態代碼塊在類加載後執行。靜態代碼塊優先於主函數執行。
- 靜態代碼塊和靜態方法相同,不能使用外部非靜態成員。
- 靜態代碼塊執行和靜態變量的初始化順序由代碼從上到下順序決定。
- 定義某個類的空變量不會加載該類,具體用到類的內容時,該類纔會被加載到內存中。
- 格式:
- 對象的初始化過程
- 類文件加載->執行類的靜態代碼塊->開闢內存空間建立對象->非靜態屬性默認初始化->非靜態屬性顯示初始化->執行構造代碼塊->構造函數初始化->將內存地址賦給棧內存中的變量
- 類文件加載->執行類的靜態代碼塊->開闢內存空間建立對象->非靜態屬性默認初始化->非靜態屬性顯示初始化->執行構造代碼塊->構造函數初始化->將內存地址賦給棧內存中的變量
- 單例設計模式
- 設計模式
- 解決某一類問題的最行之有效的辦法。
- 單例設計模式
- 保證一個類在內存只存在一個對象。
- 實現方法:
- 將構造函數私有化。
- 在類中創建一個本類對象。
- 提供一個方法用於獲取該對象。
- 實現代碼:
public class Single { private Single(){} private static Single s = new Single(); public static Single getInstance(){ return s; } }
- 注意:實際開發時,對於事物的描述不受任何影響。當需要保證該事物的對象在內存中唯一時,只需將上面三步代碼加上即可。
- 單例設計模式的兩種實現方式:懶漢式和餓漢式
- 餓漢式:類一被加載進內存,對象就創建好了。
public class Single { private Single(){} private static Single s = new Single(); public static Single getInstance(){ return s; } }
- 懶漢式:getInstance方法被調用時,對象才初始化,也叫做對象的延時加載。
由於每次進入getInstance方法都要判斷鎖,影響了程序的效率,因此可以做些改進:public class Single { private Single(){} private static Single s = null; public static synchronized Single getInstance(){ if (s == null) { s = new Single(); } return s; } }
public class Single { private Single(){} private static Single s = null; public static Single getInstance(){ if (s == null) { //如果s爲null,才進行鎖判斷 synchronized (Single.class) { //進入鎖後再次進行判斷s是否爲null //避免前面進入鎖的線程已經創建了對象 if (s == null) { s = new Single(); } } } return s; } }
- 餓漢式是線程安全的,不需要上鎖。而懶漢式存在線程安全問題,需要上鎖。
- 實際開發中,建議使用餓漢式。
- 餓漢式:類一被加載進內存,對象就創建好了。
- 繼承
- 繼承的概述
- 多個類中存在相同屬性和行爲時,將這些內容抽取到 單獨一個類中,那麼多個類無需再定義這些屬性和行 爲,只要繼承單獨的那個類即可。
- 在程序中,可以使用extends關鍵字可以讓一個類繼承另外一個類。
- 繼承的類爲子類(派生類),被繼承的類爲父類(超類, 基類)。
- 子類可以直接訪問父類中的非私有的屬性和行爲。
- 繼承的好處:
- 繼承的出現提高了代碼的複用性。
- 繼承的出現讓類與類之間產生了關係,提供了多態的前提。
- 繼承的出現提高了代碼的複用性。
- 注意:不要爲了獲取其他類的功能簡化代碼而使用繼承。類與類之間有所屬關係纔可以繼承。所屬關係:is a。
- 多個類中存在相同屬性和行爲時,將這些內容抽取到 單獨一個類中,那麼多個類無需再定義這些屬性和行 爲,只要繼承單獨的那個類即可。
- 繼承的特點
- Java只支持單繼承,不支持多繼承。
- 因爲當多個父類中定義了相同功能,當功能內容不同時,子類對象不確定要運行哪一個。
- 但是java保留了這種機制,並用另一種體現形式來表示:多實現。
- Java支持多層繼承(繼承體系)。
- 想要使用體系,要先查閱體系父類的描述,因爲父類中定義的是該體系中的共性功能。通過了解共性功能,就可以知道該體系的基本功能。
- 實際開發中,查閱父類功能,創建最子類的對象使用功能。因爲:
- 有可能父類不能創建對象。
- 創建子類對象可以使用更多的功能,包括基本的和特有的。
- Java只支持單繼承,不支持多繼承。
- 子類與父類的關係
- 子父類中變量的特點:
- 如果父類中出現非私有的與子類同名的成員變量:
- 子類要訪問本類中的變量,用this。
- 子類要訪問父類中的同名變量,用super。
- super的使用和this的使用幾乎一致。
- this代表本類對象的引用。
- super代表父類對象的引用。
- 如果父類中出現非私有的與子類同名的成員變量:
- 子父類中函數的特點:
- 當子類出現和父類一模一樣的函數時,當子類對象調用該函數,會運行子類函數的內容,如同父類的函數被覆蓋一樣。這種情況是函數的另一個特性:重寫(覆蓋)。
- 重寫要求子類權限大於等於父類權限,否則編譯失敗。
- 靜態只能覆蓋靜態。
- 重寫方法的返回類型必須與原方法的返回類型相同或者符合多態的關係。
- 父類中的私有方法不可以被覆蓋。
- 在子類覆蓋方法中,繼續使用被覆蓋的方法可以通過super.函數名獲取。
- 子父類中構造函數的特點-子類實例化過程:
- 子父類的構造函數間不存在覆蓋關係。
- 子類中所有的構造函數默認都會訪問父類中空參數的構造函數,子類每一個構造函數的第一行都有一條默認的語句 super()。
- 子類構造函數也可以顯式地調用父類的其它構造函數。
- 子類會具備父類中的數據,所以要先明確父類是如何 對這些數據初始化的。當父類中沒有空參數的構造函數時,子類的構造函數 必須通過this或者super語句指定要訪問的構造函數。
- this語句和super語句不能同時存在於一個構造函數中(包括顯式和隱式)。
- 子父類中變量的特點:
- final關鍵字
- final可以修飾類,方法,變量(成員變量、局部變量)。
- final修飾的類不可以被繼承。
- 繼承的出現打破了封裝性,爲了避免被子類覆寫功能,可以用final修飾該類。
- final修飾的方法不可以被覆蓋。
- 如果類中的部分類不希望被覆蓋,可以單獨將這些方法被final修飾。
- final修飾的變量是一個常量。只能被賦值一次。
- final標記的成員變量必須在聲明的同時或者在該類的構造函數中顯式賦值,才能使用。
- 當在描述事物時,一些數據的值是固定的。這時爲了增強閱讀性,可以給這個值起個名字,而這個值不需要改變,所以加上final修飾。
- 通常定義常量時,使用public static final功能標記該常量,這樣常量就成了全局的常量。
- 這樣定義的常量只能在定義時賦值,即使在構造函數中也不能對其進行賦值。
- 內部類只能訪問被final修飾的局部變量。
- final可以修飾類,方法,變量(成員變量、局部變量)。
- 抽象類
- 抽象類概述
- 抽象就是從多個事物中將共性的,本質的內容抽取出來。
- 抽象方法的由來:
- 多個對象都具備相同的功能,但是功能具體內容有所不同,那麼在抽取過程中,只抽取了功能定義,並未抽取功能主體,那麼只有功 能聲明,沒有功能主體的方法稱爲抽象方法。
- 多個對象都具備相同的功能,但是功能具體內容有所不同,那麼在抽取過程中,只抽取了功能定義,並未抽取功能主體,那麼只有功 能聲明,沒有功能主體的方法稱爲抽象方法。
- 抽象類:包含抽象方法的類就是抽象類。
- 抽象就是從多個事物中將共性的,本質的內容抽取出來。
- 抽象類的特點
- 抽象類和抽象方法必須用abstract關鍵字來修飾。
- 抽象類不可以被實例化,也就是不可以用new創建對象。因爲調用抽象方法沒有意義。
- 抽象類中的方法要被使用,必須由其子類覆寫所有的抽象方法後,建立子類對象調用。
如果子類只覆蓋了部分抽象方法,那麼該子類還是一個抽象類。 - 抽象類可以強制子類實現方法。
- 抽象類中可以不定義抽象方法,這樣做僅僅是爲了不讓該類建立對象。
- 抽象類和抽象方法必須用abstract關鍵字來修飾。
- 模板設計模式(template pattern)
- 描述:在定義功能時,功能的一部分是確定的,但是有一部分是不確定的,而確定的部分在使用不確定的部分,那麼這時就將不確定的部分暴露出去,由該類的子類去完成。
- 實現:
- 定義一個抽象的父類做爲模板,定義所有需要的方法。
- 在父類中實現供外界調用的主方法,將方法聲明爲final。
- 根據不同業務需求定義子類實現父類的抽象方法。
- 定義一個抽象的父類做爲模板,定義所有需要的方法。
- 舉例:
- 需求:獲取一段程序的運行時間。
- 原理:獲取程序開始和結束的時間並相減即可。
- 代碼:
打印結果:package cn.itcast.heima; class GetTime { public void getTime(){ long start = System.currentTimeMillis();//開始時間 runcode(); long end= System.currentTimeMillis();//結束時間 System.out.println("運行時間:" + (end - start) + "毫秒"); } //要運行的程序 public void runcode(){ for (int i = 0; i < 10000; i++) { System.out.print(""); } } } class TemplateDemo{ public static void main(String[] args){ GetTime gt = new GetTime(); gt.getTime(); } }
由於每次要運行的程序是不確定的,因此應該把這部分代碼定義爲抽象的,由具體的子類根據實際需求實現該方法。從而使得父類成爲一個統計程序運行時間的模板,而具體要統計什麼程序的運行時間交給子類決定。
優化後的代碼:
打印結果:package cn.itcast.heima; abstract class GetTime { public final void getTime(){ long start = System.currentTimeMillis();//開始時間 runcode(); long end= System.currentTimeMillis();//結束時間 System.out.println("運行時間:" + (end - start) + "毫秒"); } public abstract void runcode();//將要運行的程序定義爲抽象方法 } class SubTime extends GetTime{ //實現父類的抽象方法,確定具體要運行的程序代碼 public void runcode(){ for (int i = 0; i < 10000; i++) { System.out.print(""); } } } class TemplateDemo{ public static void main(String[] args){ GetTime gt = new SubTime();//定義子類對象 gt.getTime(); } }
- 接口
- 接口概述
- 接口是一種特殊的抽象類,接口中聲明的所有方法都是抽象的。
- 格式:
interface {} - 接口中的成員修飾符是固定的。
- 成員常量:public static final
- 成員函數:public abstract
- 成員常量:public static final
- 接口不可以創建對象,因爲有抽象方法。只有子類實現該接口,且對接口中的方法全部覆蓋後,子類纔可以實例化。否則子類是一個抽象類。
- 接口經過編譯也生成類文件。允許使用接口名.成員變量的方法訪問成員變量。
- 接口的出現將“多繼承”通過另一種形式體現出來,即“多實現”。
- 接口之間支持“多繼承”,但是接口之間的多繼承不允許出現返回類型不同的同名函數,否則編譯失敗。
- 接口是一種特殊的抽象類,接口中聲明的所有方法都是抽象的。
- 接口的特點
- 接口是對外暴露的規則。
- 接口是程序的功能擴展。
- 接口可以用來多實現。
- 類與接口之間是實現關係,而且類可以 繼承一個類的同時實現多個接口。
- 接口與接口之間可以有繼承關係。
- 接口是對外暴露的規則。
- 多態
- 多態概述
- 多態就是某一類事物的多種存在形態。
- 例如:
動物中貓,狗。
貓這個對象對應的類型是貓類型。
貓x = new 貓();
同時貓也是動物中的一種,也可以把貓稱爲 動物。
動物y = new 貓();
動物是貓和狗具體事物中抽取出來的父類型。
父類型引用指向了子類對象。 - 多態的體現:
- 父類或者接口的引用指向或者接收自己的子類對象。
- 父類或者接口的引用指向或者接收自己的子類對象。
- 多態的前提:
- 需要存在繼承或者實現關係。
- 要有覆蓋操作。
- 需要存在繼承或者實現關係。
- 多態的好處:
- 多態的存在提高了程序的擴展性和後期可維護性。
- 多態的存在提高了程序的擴展性和後期可維護性。
- 多態的弊端:
- 只能使用父類的引用訪問父類中的成員。
- 只能使用父類的引用訪問父類中的成員。
- 多態就是某一類事物的多種存在形態。
- 多態的轉型
- Animal a = new Cat();//類型提升。類的向上轉型。
Cat c = (Cat)a;//如果想要調用貓的特有方法時,需要強制將父類的引用轉成子類類型。類的向下轉型。 - 父類的引用可以強轉成子類類型,父類的對象不可以強轉成子類類型。
- Animal a = new Cat();//類型提升。類的向上轉型。
- 多態的特點
- 非靜態成員函數:
- 編譯時:要查看引用變量所屬的類中是否有所調用的方法。
- 在運行時:要查看對象所屬的類中是否有所調用的方法。
- 總結:成員函數在多態調用時,編譯看左邊,運行看右邊。
- 編譯時:要查看引用變量所屬的類中是否有所調用的方法。
- 靜態成員函數:
- 無論編譯和運行,都參考左邊。
- 成員變量:
- 無論編譯和運行,都參考左邊(引用變量所屬的類)。
- 類的一個成員若想表現多態必須可以被覆蓋:
- 對於成員變量而言,不會發生覆蓋現象(會隱藏),在子類出現相同變量的定義時只會隱藏父類變量,因此不會表現多態。同時變量調用在編譯時就會解析,不符合動態綁定的特徵。
- 在成員方法中,靜態方法和final方法(private方法)也不會發生覆蓋現象(會隱藏),因此也不會表現多態性。
- 對於成員變量而言,不會發生覆蓋現象(會隱藏),在子類出現相同變量的定義時只會隱藏父類變量,因此不會表現多態。同時變量調用在編譯時就會解析,不符合動態綁定的特徵。
- 動態綁定和靜態綁定:
- 靜態綁定:在程序執行前方法已經被綁定,此時由編譯器或其它連接程序實現。簡單的可以理解爲程序編譯期的綁定;java當中的方法只有final,static,private和構造方法是前期綁定。
- 動態綁定:在運行時根據具體對象的類型進行綁定。
- 非靜態成員函數:
- Object類
- 概述
- Object類是所有對象的直接或者間接父類。
- 該類中該定義的是所有對象都具備的功能。
- equals方法
- Object類中已經提供了對象是否相同的比較方法。
- 如果自定義類中也要比較相同的同能,只要覆蓋Object中的equals方法,建立自己特有的比較內容即可。
- toString方法
- toString()方法返回的是對象的字符串表示。
- 所有的類都可以覆蓋Object類的toString()方法實現自己的顯示功能。
- toString()方法返回的是對象的字符串表示。
- 內部類
- 定義
- 將一個類定義在另一個類的裏面,對裏面那個 類就稱爲內部類(內置類,嵌套類)。
- 將一個類定義在另一個類的裏面,對裏面那個 類就稱爲內部類(內置類,嵌套類)。
- 訪問特點
- 內部類可以直接訪問外部類中的成員,包括私有成員。
之所以可以直接訪問外部類中的成員,是因爲內部類中持有一個對外部類的引用,格式爲:外部類名.this - 外部類要訪問內部類中的成員必須要建立內部類的對象。
- 其它外部類直接訪問非私有內部類成員的方法:
- 外部類名.內部類名 變量名 = 外部類對象.內部類對象
- 外部類名.內部類名 變量名 = 外部類對象.內部類對象
- 當內部類在成員位置上時,就可以被成員修飾符修飾,比如:
private:將內部類在外部類中進行封裝。
static:當內部類被static修飾後,只能直接訪問外部類中的static成員,出現了訪問侷限。 - 內部類訪問外部類的成員變量:
外部類.this.變量名
- 內部類可以直接訪問外部類中的成員,包括私有成員。
- 靜態內部類
- 靜態內部類不用創建外部類對象就可以直接創建對象:
- 外部類名.內部類名 變量名 = new 外部類名.內部類名();
- 在其它外部類中,如何直接訪問static內部類的非靜態成員:
- new 外部類名.內部類名().函數名();
- new 外部類名.內部類名().函數名();
- 在其它外部類中,如何直接訪問static內部類的靜態成員:
- 外部類名.內部類名().函數名();
- 外部類名.內部類名().函數名();
- 如果內部類定義了靜態成員,該內部類必須是靜態的。
- 如果外部類的靜態方法訪問內部類,該內部類必須是靜態的。
- 靜態內部類不用創建外部類對象就可以直接創建對象:
- 局部內部類
- 局部內部類也可以訪問外部類的成員。
- 局部內部類不能用static修飾,static只修飾成員。
- 局部內部類裏面不能定義靜態方法。
- 如果內部類訪問局部變量,該變量必須被final修飾。
- 局部內部類也可以訪問外部類的成員。
- 匿名內部類
- 匿名內部類就是內部類的簡化寫法。如果一個類只使用一次,那麼可以定義爲匿名內部類。
- 定義匿名內部類的前提:
- 內部類必須繼承或實現一個外部類或者接口。
- 內部類必須繼承或實現一個外部類或者接口。
- 定義匿名內部類的格式:
- new 外部類名或者接口名(){
覆蓋類或者接口中的代碼, (也可以自定義內容。)
}
- new 外部類名或者接口名(){
- 匿名內部類就是一個匿名子類對象。
- 匿名內部類中定義的方法最好不要超過3個。
- 匿名內部類就是內部類的簡化寫法。如果一個類只使用一次,那麼可以定義爲匿名內部類。
- 異常
- 異常概述
- 異常就是Java程序在運行過程中出現的錯誤。如程序要打開一個不存的文件、網絡連接中斷、操作數組越界、裝載一個不存在的類等。Java通過類的形式將其封裝成對象。
- 異常的體系:
- Throwable
- Error:通常出現重大問題如,運行的類不存在或者內存溢出等。不編寫針對代碼對其處理。
- Exception:在運行時運行出現的一些情況,可以編寫針對性的代碼對其處理。
- Error:通常出現重大問題如,運行的類不存在或者內存溢出等。不編寫針對代碼對其處理。
- Throwable
- Exception和Error的子類名都是以父類名作爲後綴。
- 異常的好處:
- 將問題進行封裝。
- 將正常流程代碼和問題處理代碼相分離,方便於閱讀。
- 異常就是Java程序在運行過程中出現的錯誤。如程序要打開一個不存的文件、網絡連接中斷、操作數組越界、裝載一個不存在的類等。Java通過類的形式將其封裝成對象。
- Throwable中的方法
- getMessage():獲取異常信息,返回字符串。
- toString():獲取異常類名和異常信息,返回字符串。
- printStackTrace():獲取異常類名和異常信息,以及異常出現在程序中的位置。返回值void。
- printStackTrace(PrintStream s):通常用該方法將異常內容保存在日誌文件中,以便查閱。
- getMessage():獲取異常信息,返回字符串。
- 異常的處理
- 使用try……catch語句進行捕獲,finally可以結合try……catch使用,出現異常,finally裏面的代碼也會執行。
Finally代碼塊只有一種情況不會被執行。就是在之前執行了System.exit(0)。 - 在程序中可以在方法後面使用throws關鍵字聲明向外拋出異常。聲明該功能可能會出現問題。
- 使用try……catch語句進行捕獲,finally可以結合try……catch使用,出現異常,finally裏面的代碼也會執行。
- 多異常處理
- 聲明異常時,建議聲明更爲具體的異常,這樣處理可以更具體。
- 聲明幾個異常,就對應幾個catch塊。
- 如果異常出現繼承關係,父類異常catch塊放在最下面。
- 建立進行catch處理時,catch中一定要定義具體的處理方式。不要簡單地定義e.printStackTrace(),也不要簡單地打印一條輸出語句。
- 可以將異常內容保存在日誌文件中。
- 可以將異常內容保存在日誌文件中。
- 自定義異常
- 自定義類繼承Exception或者其子類。
- 因爲項目中會出現特有的問題,而這些問題並未被Java鎖描述並封裝成對象。
- 對應這些特有的問題,可以按照Java對問題封裝的思想,將特有的問題進行自定義的異常封裝。
- 可拋性是Throwable體系中獨有的特點。只有這個體系中的類和對象纔可以被throws和throw操作。
- 通過throw關鍵字手動拋出自定義異常對象
- 處理函數拋出的自定義異常:
- 要麼在內部try-catch處理。
- 要麼在函數上聲明讓調用者處理。
- 自定義類繼承Exception或者其子類。
- throws和throw
- thorws用在函數上,後面跟異常類名,可以跟多個,用逗號隔開。
- throw用在函數內,後面跟異常對象。
- thorws用在函數上,後面跟異常類名,可以跟多個,用逗號隔開。
- RuntimeException
- 如果在函數內拋出該異常,函數上可以不用聲明,編譯可以通過。
- 如果在函數上聲明瞭該異常,調用者可以不用進行處理,編譯可以通過。
- 之所以不用再函數聲明,是因爲不需要讓調用者處理。當該異常發生,希望程序停止。因爲在運行時,出現了無法繼續運算的情況,需要對代碼進行修正。
- 自定義異常時,如果該異常的發生,導致無法再繼續進行運行,就讓自定義異常繼承RuntimeException。
- 除了RuntimeException的其它異常爲編譯時異常。
- finally
- finally中存放的是一定會被執行的代碼。
- 通常關閉資源的動作都放在finally中。保證即使程序出現異常,也能正常關閉資源。
- 在分層設計時,異常要在層內封裝。
- 出現異常時,要在本層內處理,並把本層無法解決的相關問題轉換爲其它異常,繼續向上層拋出。
- 異常處理的三種格式:
- try-catch
- try-catch-finally
- try-finally
- try-catch
- 覆蓋時的異常特點
- 如果父類方法拋出了異常,那麼子類在覆蓋父類方法時,只能拋出該異常或該異常的子類。
- 如果父類方法拋出了多個異常,那麼子類在覆蓋父類方法時,只能拋出父類異常的子集。
- 如果子類方法發生了父類沒有的異常,就只能在方法內進行try-catch處理,不能拋出。
- 如果父類方法拋出了異常,那麼子類在覆蓋父類方法時,只能拋出該異常或該異常的子類。
- 包(package)
- 對類文件進行分類管理。
- 給類提供多層命名空間。
- 寫在程序文件的第一行。
- 類名的全稱的是 包名.類名。
- 包也是一種封裝形式。
- 包與包之間訪問,被訪問的包中的類及類中的成員,必須被public修飾。
- 不同包中的子類可以訪問父類中被protected修飾的成員。
- 類成員之間的四種訪問權限:
- import:
- 簡化類名。
- 一個程序文件中只有一個package,可以有多個import。
- 用來導包中的類,不導入包中的包。
- 簡化類名。
- Jar包
- Java的壓縮包
- 方便項目的攜帶。
- 方便於使用,只要在classpath設置jar路徑即可。
- 數據庫驅動,SSH框架等都是以jar包體現的。
- 方便項目的攜帶。
- 可以將類文件用jar命令壓縮成jar包,並配置相應的classpath環境變量爲jar包路徑(包含jar包名)。
- 封裝好的jar包放到classpath路徑下就可以參考說明文檔直接使用了,非常方便。
- DOS下的數據重定向命令:> 路徑
- java的類庫:jre下的lib\rt.jar
java的編譯環境工具類:jdk下的lib\tools.jar
java的源文件:jdk下的src.zip - 通過jar.exe工具對jar的操作:
- 創建jar包:
jar -cvf mypack.jar packa packb - 查看jar包:
jar -tvf mypack.jar [>定向文件] - 解壓縮:
jar -xvf mypack.jar - 自定義jar包的清單文件:
jar –cvfm mypack.jar mf.txt packa packb
- 創建jar包:
- jar命令:
- 用法: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
選項包括:
-c 創建新的歸檔文件
-t 列出歸檔目錄
-x 從檔案中提取指定的 (或所有) 文件
-u 更新現有的歸檔文件
-v 在標準輸出中生成詳細輸出
-f 指定歸檔文件名
-m 包含指定清單文件中的清單信息
-e 爲捆綁到可執行 jar 文件的獨立應用程序指定應用程序入口點
-0 僅存儲; 不使用情況任何 ZIP 壓縮
-M 不創建條目的清單文件
-i 爲指定的 jar 文件生成索引信息
-C 更改爲指定的目錄幷包含其中的文件 - 如果有任何目錄文件, 則對其進行遞歸處理。
- 清單文件名, 歸檔文件名和入口點名稱的指定順序與 'm', 'f' 和 'e' 標記的指定順序相同。
- 示例 1: 將兩個類文件歸檔到一個名爲 classes.jar 的歸檔文件中:
- jar cvf classes.jar Foo.class Bar.class
- 示例 2: 使用現有的清單文件 'mymanifest' 並將 foo/ 目錄中的所有文件歸檔到 'classes.jar' 中:
- jar cvfm classes.jar mymanifest -C foo/。
- 用法: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
- Java的壓縮包