面向對象特征: 封裝虐译,繼承,多態(tài)
封裝:把屬性隱藏烛卧,提供公共方法對其訪問(private 封裝特性的一種)
面向對象舉例:利用對象的方法
面向過程:一步一步執(zhí)行過程
靜態(tài)變量、靜態(tài)方法
- 靜態(tài)變量:對象之間共享數(shù)據(jù)
- 靜態(tài)方法:
- 靜態(tài)方法只能訪問靜態(tài)成員[1]残吩,實例方法可以訪問靜態(tài)和實例成員。
- 調(diào)用靜態(tài)方法可以無需創(chuàng)建對象(即"類名.方法名")
構造函數(shù)
作用:可以用于給對象進行初始化
默認構造函數(shù)的訪問權限:
默認構造函數(shù)的訪問權限和所屬類一致
即:類被public修飾倘核,那么默認構造函數(shù)也帶public修飾(private同理)
構造函數(shù)與自定義函數(shù)區(qū)別:
寫法上:
- 構造函數(shù)-無返回值
- 自定義函數(shù)-返回值可有可無
調(diào)用時機:
- 構造函數(shù)-對象創(chuàng)建是調(diào)用
- 自定義函數(shù)-由實例對象調(diào)用
main方法
- 必須定義為:public static void main(String args[])泣侮,這是Java的規(guī)范。
- 程序的入口紧唱,類被創(chuàng)建時旁瘫,不會被調(diào)用
final關鍵字
final在Java中是一個保留的關鍵字,可以聲明成員變量琼蚯、方法酬凳、類以及本地變量。一旦你將引用聲明作final遭庶,你將不能改變這個引用了宁仔,編譯器會檢查代碼,如果你試圖將變量再次初始化的話峦睡,編譯器會報編譯錯誤
final變量
只能賦值一次即可修飾成員變量翎苫,也可修飾局部變量
final變量經(jīng)常和static關鍵字一起使用,作為常量榨了。
final方法
方法前面加上final關鍵字煎谍,代表這個方法不可以被子類的方法重寫。
如果你認為一個方法的功能已經(jīng)足夠完整了龙屉,子類中不需要改變的話呐粘,你可以聲明此方法為final。final方法比非final方法要快转捕,因為在編譯的時候已經(jīng)靜態(tài)綁定了作岖,不需要在運行時再動態(tài)綁定。
final類
final類通常功能是完整的五芝,它們不能被繼承痘儡,被子類復寫功能
Java中有許多類是final的,譬如String, Interger以及其他包裝類枢步。
final優(yōu)點
- final關鍵字提高了性能沉删。JVM和Java應用都會緩存final變量。
- final變量可以安全的在多線程環(huán)境下進行共享醉途,而不需要額外的同步開銷矾瑰。
- 使用final關鍵字,JVM會對方法结蟋、變量及類進行優(yōu)化脯倚。
final的重要知識點
- final關鍵字可以用于成員變量渔彰、本地變量嵌屎、方法以及類推正。
- final成員變量必須在聲明的時候初始化或者在構造器中初始化,否則就會報編譯錯誤宝惰。
你不能夠對final變量再次賦值植榕。- final本地變量必須在聲明時賦值。
- 在匿名類中所有變量都必須是final變量尼夺。
- final方法不能被重寫尊残。
- final類不能被繼承。
- final關鍵字不同于finally關鍵字淤堵,后者用于異常處理寝衫。
- final關鍵字容易與finalize()方法搞混,后者是在Object類中定義的方法拐邪,是在垃圾回收之前被JVM調(diào)用的方法慰毅。
- 接口中聲明的所有變量本身是final的。
- final和abstract這兩個關鍵字是反相關的扎阶,final類就不可能是abstract的汹胃。
- final方法在編譯階段綁定,稱為靜態(tài)綁定(static binding)东臀。
- 沒有在聲明時初始化final變量的稱為空白final變量(blank final variable)着饥,它們必須在構造器中初始化,或者調(diào)用this()初始化惰赋。不這么做的話宰掉,編譯器會報錯“final變量(變量名)需要進行初始化”。
- 將類赁濒、方法贵扰、變量聲明為final能夠提高性能,這樣JVM就有機會進行估計流部,然后優(yōu)化戚绕。
- 按照Java代碼慣例,final變量就是常量枝冀,而且通常常量名要大寫
抽象類
在了解抽象類之前舞丛,先來了解一下抽象方法:
抽象方法是一種特殊的方法,它只有聲明果漾,而沒有具體的實現(xiàn)球切。
抽象方法的聲明格式為:
abstract void fun(); // 抽象方法必須用abstract關鍵字進行修飾
如果一個類含有抽象方法,則稱這個類為抽象類
- 抽象類必須在類前用abstract關鍵字修飾
- 抽象類可以有構造函數(shù)(子類創(chuàng)建對象前被調(diào)用)绒障,但不能用抽象類創(chuàng)建對象吨凑,因為抽象類中含有無具體實現(xiàn)的方法
- 抽象方法必須為public或者protected(因為如果為private,則不能被子類繼承,子類便無法實現(xiàn)該方法)鸵钝,缺省情況下默認為public
- 如果一個類繼承于一個抽象類糙臼,則子類必須實現(xiàn)父類的抽象方法。如果子類沒有實現(xiàn)父類的抽象方法恩商,則必須將子類也定義為為abstract類
在其他方面变逃,抽象類和普通的類并沒有區(qū)別(可以擁有成員變量和普通的成員方法)。
接口
接口怠堪,英文稱作interface揽乱,在軟件工程中,接口泛指供別人調(diào)用的方法或者函數(shù)粟矿。從這里咐汞,我們可以體會到Java語言設計者的初衷萝究,它是對行為的抽象。在Java中,定一個接口的形式如下:
[public] interface InterfaceName {
}
接口中可以含有 變量和方法荣病。但是要注意:
- 接口中的變量會被隱式地指定為public static final變量(并且只能是public static final變量销凑,用private修飾會報編譯錯誤)
- 方法會被隱式地指定為public abstract方法且只能是public abstract方法(用其他關鍵字焙贷,比如private缩抡、protected、static哗讥、 final等修飾會報編譯錯誤)嚷那,并且接口中所有的方法不能有具體的實現(xiàn),也就是說杆煞,接口中的方法必須都是抽象方法
從這里可以隱約看出接口和抽象類的區(qū)別魏宽,接口是一種極度抽象的類型,它比抽象類更加“抽象”决乎,并且一般情況下不在接口中定義變量队询。
要讓一個類遵循某組特地的接口需要使用implements關鍵字,具體格式如下:
class ClassName implements Interface1,Interface2,[....]{
}
可以看出:
- 允許一個類遵循多個特定的接口
- 如果一個非抽象類遵循了某個接口构诚,就必須實現(xiàn)該接口中的所有方法蚌斩。對于遵循某個接口的抽象類,可以不實現(xiàn)該接口中的抽象方法
抽象類和接口的區(qū)別
語法層面上的區(qū)別
- 抽象類可以提供成員方法的實現(xiàn)細節(jié)范嘱,而接口中只能存在public abstract 方法
- 抽象類中的成員變量可以是各種類型的送膳,而接口中的成員變量只能是public static final類型的
- 接口中不能含有靜態(tài)代碼塊以及靜態(tài)方法,而抽象類可以有靜態(tài)代碼塊和靜態(tài)方法
- 一個類只能繼承一個抽象類丑蛤,而一個類卻可以實現(xiàn)多個接口
- 抽象類不能被實例化叠聋,但可以有構造方法,接口中不能有構造方法
設計層面上的區(qū)別
單例模式
- 單例類只能有一個實例
- 單例類必須自己創(chuàng)建自己的唯一實例
- 單例類必須給所有其他對象提供這一實例
單例的實現(xiàn)
- 構造函數(shù)權限 private
- 對象是static屬性 (保證內(nèi)存只存一份)
- 接口 static
繼承
如何使用繼承體系中的功能
- 要使用體系受裹,首先查閱體系父類的描述碌补,因為父類中定義的是該體系中"共性功能"
- 通過了解共性功能,就可以知道該體系的基本功能。
為什么在具體調(diào)用時厦章,要創(chuàng)建最子類的對象镇匀?
- 可能是因為父類不能創(chuàng)建對象
- 創(chuàng)建子類對象可以使用更多的功能,包括父類的+自己特有的
重寫(也稱覆蓋)
- 子類覆蓋父類權限 只能大于等于
- 靜態(tài)只能覆蓋靜態(tài) (生存周期不一樣)
多態(tài)
多態(tài)指允許不同類的對象對同一消息做出響應闷袒。即同一消息可以根據(jù)發(fā)送對象的不同而采用多種不同的行為方式。(發(fā)送消息就是函數(shù)調(diào)用)
舉個例子:
比方說按下 F1 鍵這個動作岩梳,如果當前在 Flash 界面下彈出的就是 AS 3 的幫助文檔囊骤;如果當前在 Word 下彈出的就是 Word 幫助;在 Windows 下彈出的就是 Windows 幫助和支持冀值。同一個事件發(fā)生在不同的對象上會產(chǎn)生不同的結果也物。
多態(tài)存在的三個必要條件
- 要有繼承
- 要有重寫
- 父類引用指向子類對象
多態(tài)的好處
- 可替換性(substitutability)。多態(tài)對已存在代碼具有可替換性列疗。例如滑蚯,多態(tài)對圓Circle類工作,對其他任何圓形幾何體抵栈,如圓環(huán)告材,也同樣工作
- 可擴充性(extensibility)。多態(tài)對代碼具有可擴充性古劲。增加新的子類不影響已存在類的多態(tài)性斥赋、繼承性,以及其他特性的運行和操作产艾。實際上新加子類更容易獲得多態(tài)功能疤剑。例如,在實現(xiàn)了圓錐闷堡、半圓錐以及半球體的多態(tài)基礎上隘膘,很容易增添球體類的多態(tài)性
- 接口性(interface-ability)。多態(tài)是超類通過方法簽名杠览,向子類提供了一個共同接口弯菊,由子類來完善或者覆蓋它而實現(xiàn)的
- 靈活性(flexibility)。它在應用中體現(xiàn)了靈活多樣的操作踱阿,提高了使用效率误续。
- 簡化性(simplicity)。多態(tài)簡化對應用軟件的代碼編寫和修改過程扫茅,尤其在處理大量對象的運算和操作時蹋嵌,這個特點尤為突出和重要。
內(nèi)部類
- 內(nèi)部類可以直接訪問外部類中的成員葫隙,包括私有
- 外部類要訪問內(nèi)部類栽烂,必須建立內(nèi)部類對象
內(nèi)部類訪問格式
當內(nèi)部類定義在外部類的成員位置上,且非私有。創(chuàng)建內(nèi)部類的格式:
外部類名.內(nèi)部類名 變量名 = 外部類對象.內(nèi)部類對象;
Outer.Inter inter = new Outer.new Inter();
內(nèi)部類定義在局部時:
- 不可以被成員修飾符修飾
- 可以直接訪問外部類中的成員 //因為持有外部類中的引用
- 不可以訪問它所在的局部中變量腺办。只能訪問被final修飾的局部變量
異常
嚴重問題Error類
非常嚴重問題Exception類
Throwable
Error
RuntimeException
Exception
異常信息打印
- e.getMessage() //打印異常信息
- e.toString() //異常名稱+異常信息
- e.printStackTrace() //異常名稱,異常信息,異常出現(xiàn)的位置(jvm默認異常處理機制就是調(diào)用 printStackTrace())
集合
List
有序焰手,可重復
Set
無序,不可重復
Map
無序怀喉,key不可重復书妻,value可重復
Iterator遍歷的添加、刪除
// 添加
List list = new ArrayList<String>();
Iterator it = list.iterator();
List<String> newList = new ArrayList<String>();
while(it.hasNext){
Object obj = it.next;
if(obj.equals('5')){
newList.add(obj);
}
}
list.addAll(newList)
// 刪除
List list = new ArrayList<String>();
Iterator it = list.iterator();
while(it.hasNext){
Object obj = it.next;
if(obj == '5'){
it.remove();
}
}
加載順序
靜態(tài)變量躬拢、靜態(tài)塊——>main方法——>成員變量(匿名塊屬于成員變量)——>構造方法——>方法(靜態(tài)躲履、非靜態(tài))
同級的加載順序由編寫先后決定
public class test { //1.第一步,準備加載類
public static void main(String[] args) {
new test(); //4.第四步聊闯,new一個類工猜,但在new之前要處理匿名代碼塊
}
static int num = 4; //2.第二步,靜態(tài)變量和靜態(tài)代碼塊的加載順序由編寫先后決定
{
num += 3;
System.out.println("b"); //5.第五步菱蔬,按照順序加載匿名代碼塊篷帅,代碼塊中有打印
}
int a = 5; //6.第六步,按照順序加載變量
{ // 成員變量第三個
System.out.println("c"); //7.第七步拴泌,按照順序打印c
}
test() { // 類的構造函數(shù)魏身,第四個加載
System.out.println("d"); //8.第八步,最后加載構造函數(shù)蚪腐,完成對象的建立
}
static { // 3.第三步叠骑,靜態(tài)塊,然后執(zhí)行靜態(tài)代碼塊削茁,因為有輸出宙枷,故打印a
System.out.println("a");
}
static void run() // 靜態(tài)方法,調(diào)用的時候才加載// 注意看茧跋,e沒有加載
{
System.out.println("e");
}
}
存在繼承關系時的加載順序
public class Print {
public Print(String s){
System.out.print(s + " ");
}
}
public class Parent{
public static Print obj1 = new Print("1");
public Print obj2 = new Print("2");
public static Print obj3 = new Print("3");
static{
new Print("4");
}
public static Print obj4 = new Print("5");
public Print obj5 = new Print("6");
public Parent(){
new Print("7");
}
}
public class Child extends Parent{
static{
new Print("a");
}
public static Print obj1 = new Print("b");
public Print obj2 = new Print("c");
public Child (){
new Print("d");
}
public static Print obj3 = new Print("e");
public Print obj4 = new Print("f");
public static void main(String [] args){
Parent obj1 = new Child ();
Parent obj2 = new Child ();
}
}
執(zhí)行main方法慰丛,程序輸出順序為: 1 3 4 5 a b e 2 6 7 c f d 2 6 7 c f d
輸出結果表明,程序的執(zhí)行順序為:
如果類還沒有被加載:1瘾杭、先執(zhí)行父類的靜態(tài)代碼塊和靜態(tài)變量初始化诅病,并且靜態(tài)代碼塊和靜態(tài)變量的執(zhí)行順序只跟代碼中出現(xiàn)的順序有關。
2粥烁、執(zhí)行子類的靜態(tài)代碼塊和靜態(tài)變量初始化贤笆。
3、執(zhí)行父類的實例變量初始化
4讨阻、執(zhí)行父類的構造函數(shù)
5芥永、執(zhí)行子類的實例變量初始化
6、執(zhí)行子類的構造函數(shù)如果類已經(jīng)被加載:
則靜態(tài)代碼塊和靜態(tài)變量就不用重復執(zhí)行钝吮,再創(chuàng)建類對象時埋涧,只執(zhí)行與實例相關的變量初始化和構造方法板辽。
網(wǎng)絡編程
UDP
將數(shù)據(jù)及源和目的封裝在數(shù)據(jù)包中,區(qū)需要建立連接
每個數(shù)據(jù)報的大小限制在64K內(nèi)
因無連接棘催,是不可靠協(xié)議
不需要建立連接劲弦,速度快
TCP
建立連接,形成傳輸數(shù)據(jù)的通道
在連接中進行大數(shù)據(jù)量傳輸
三次握手醇坝,是可靠協(xié)議
必須建立連接邑跪,效率會稍低
-
之所以不允許靜態(tài)方法訪問實例成員變量,是因為實例成員變量是屬于某個對象的呼猪,而靜態(tài)方法在執(zhí)行時画畅,并不一定存在對象。同樣郑叠,因為實例方法可以訪問實例成員變量夜赵,如果允許靜態(tài)方法調(diào)用實例方法明棍,將間接地允許它使用實例成員變量乡革,所以它也不能調(diào)用實例方法√福基于同樣的道理沸版,靜態(tài)方法中也不能使用關鍵字this` ?