Java語(yǔ)言中面向?qū)ο蟮奶匦?/p>
Java自動(dòng)的“無(wú)用單元收集”預(yù)防存儲(chǔ)漏泄和其它有關(guān)動(dòng)態(tài)存儲(chǔ)分配和解除分配的有害錯(cuò)誤。Java解釋程序也執(zhí)行許多運(yùn)行時(shí)的檢查,諸如驗(yàn)證所有數(shù)組和串訪問(wèn)是否在界限之內(nèi)。下面是小編整理的關(guān)于Java語(yǔ)言中面向?qū)ο蟮奶匦,希望大家認(rèn)真閱讀!
Java面向?qū)ο?/strong>
面向?qū)ο笫且环N程序設(shè)計(jì)方法,或者是程序設(shè)計(jì)規(guī)范,其基本思想是使用對(duì)象、類、繼承、封裝、多態(tài)等基本概念來(lái)進(jìn)行程序設(shè)計(jì)。 面向?qū)ο笫且环N符合人們思考習(xí)慣的思想,可以將復(fù)雜的事情簡(jiǎn)單化,將程序員從執(zhí)行者轉(zhuǎn)換成了指揮者
完成需求時(shí):
• 先要去找具有所需的功能的對(duì)象來(lái)用。
• 如果該對(duì)象不存在,那么創(chuàng)建一個(gè)具有所需功能的對(duì)象。
• 這樣簡(jiǎn)化開(kāi)發(fā)并提高代碼的復(fù)用。
面向?qū)ο蟮拈_(kāi)發(fā)過(guò)程其實(shí)就是不斷的創(chuàng)建對(duì)象,使用對(duì)象,指揮對(duì)象做事情。設(shè)計(jì)的過(guò)程其實(shí)就是在管理和維護(hù)對(duì)象之間的關(guān)系。
面向?qū)ο蟮奶卣鳎?/p>
• 封裝(encapsulation)
• 繼承(inheritance)
• 多態(tài)(polymorphism)
1.封裝
概念:是指隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外提供公共訪問(wèn)方式。
好處:• 將變化隔離。• 便于使用。• 提高重用性。• 提高安全性。
封裝原則:
• 將不需要對(duì)外提供的內(nèi)容都隱藏起來(lái)。
• 把屬性都隱藏,提供公共方法對(duì)其訪問(wèn)。
Java中可以通過(guò)對(duì)類的成員設(shè)置一定的訪問(wèn)權(quán)限,實(shí)現(xiàn)類中成員的信息隱藏。
private:類中限定為private的成員,只能被這個(gè)類本身訪問(wèn)。如果一個(gè)類的構(gòu)造方法聲明為private,則其它類不能生成該類的一個(gè)實(shí)例。
default:類中不加任何訪問(wèn)權(quán)限限定的成員屬于缺省的(default)訪問(wèn)狀態(tài),可以被這個(gè)類本身和同一個(gè)包中的類所訪問(wèn)。
protected:類中限定為protected的成員,可以被這個(gè)類本身、它的子類(包括同一個(gè)包中以及不同包中的子類)和同一個(gè)包中的所有其他的類訪問(wèn)。
public:類中限定為public的成員,可以被所有的類訪問(wèn)。
如下面的這個(gè)student類,就是使用了封裝,將類中的屬性name 、age和score私有化,使外部不能直接訪問(wèn)他們,只能通過(guò)public類型的對(duì)他們方法進(jìn)行操作。
class Student {
private String name;//聲明屬性 ,并設(shè)為私有類型,起到封裝的作用
private int age;
private int score;
public Student(String name,int age ,int score) { //構(gòu)造函數(shù),分別給name、age、score賦值
this.name= name;// :this代本類對(duì)象的引用
this.age= age;
this.score= score;
}
public String getName() { //設(shè)置getter方法,因?yàn)樽兞吭O(shè)為了私有,對(duì)象無(wú)法訪問(wèn)類中的屬性,需要用getter方法獲取變量
return name;
}
public void setName(String name) { //設(shè)置setter方法,因?yàn)樽兞吭O(shè)為了私有,對(duì)象無(wú)法訪問(wèn)類中的屬性,需要用setter方法給變量賦值
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScorre() {
return score;
}
public void setScorre(int score) {
this.score = score;
}
}
2.繼承
繼承是一種聯(lián)結(jié)類的層次模型,并且允許和鼓勵(lì)類的重用,它提供了一種明確表述共性的方法。對(duì)象的一個(gè)新類可以從現(xiàn)有的類中派生,這個(gè)過(guò)程稱為類繼承。
新類繼承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的`基類那里繼承方法和實(shí)例變量,并且類可以修改或增加新的方法使之更適合特殊的需要。
子類可以直接訪問(wèn)父類中的非私有的屬性和行為。通過(guò) extends 關(guān)鍵字讓類與類之間產(chǎn)生繼承關(guān)系。如下:class SubDemo extends Demo{}
繼承提高了代碼的復(fù)用性。
繼承的出現(xiàn)讓類與類之間產(chǎn)生了關(guān)系,提供了多態(tài)的前提
繼承的特點(diǎn):
Java只支持單繼承,不支持多繼承。
• 一個(gè)類只能有一個(gè)父類,不可以有多個(gè)父類。
• class SubDemo extends Demo{} //這是對(duì)的
• class SubDemo extends Demo1,Demo2...//這是錯(cuò)的
Java支持多層繼承(繼承體系)
• class A{}
• class B extends A{}
• class C extends B{}
定義繼承需要注意:
• 不要僅為了獲取其他類中某個(gè)功能而去繼承
• 類與類之間要有所屬關(guān)系,xx1是xx2的一種。
如:
class Ren { //父類
int age=20;
String name="wk";
Super.sho
public void show() {
System.out.println("姓名:"+name+" 年齡:"+age);
}
}
class Sudents extends Ren {//子類Sudents繼承了父類Ren
int score=90;//增加了新的屬性
int age= super.age+1;//使用super標(biāo)記父類中的元素,修改了Ren中age的值
public void show() {//重寫了父類中的方法( 覆蓋時(shí),子類方法權(quán)限一定要大于等于父類方法權(quán)限,靜態(tài)只能覆蓋靜態(tài)。)
System.out.println("姓名:"+name+" 年齡:"+age+" 分?jǐn)?shù):"+ score);// Sudents繼承了Ren,所以Ren中的屬性name和age在Sudents可以直接使用
}
}
public class Preson {
public static void main(String[] args) {
Ren ren = new Ren();//聲明一個(gè)Ren對(duì)象
Sudents sudents = new Sudents();//聲明一個(gè)Sudents對(duì)象
ren.show();
sudents.show();
}
}
程序運(yùn)行結(jié)果是:
super和this的用法相同:this代表本類應(yīng)用 ;super代表父類引用 。當(dāng)子父類出現(xiàn)同名成員時(shí),可以用super進(jìn)行區(qū)分 ,子類要調(diào)用父類構(gòu)造函數(shù)時(shí),可以使用super語(yǔ)句。
在子類覆蓋方法中,繼續(xù)使用被覆蓋的方法可以通過(guò)super.函數(shù)名獲取。
注意:
1. 子類中所有的構(gòu)造函數(shù)默認(rèn)都會(huì)訪問(wèn)父類中空參數(shù)的構(gòu)造函數(shù),因?yàn)槊恳粋(gè)構(gòu)造函數(shù)的第一行都有一條默認(rèn)的語(yǔ)句 super();子類會(huì)具備父類中的數(shù)據(jù),所以要先明確父類是如何對(duì)這些數(shù)據(jù)初始化的。當(dāng)父類中沒(méi)有空參數(shù)的構(gòu)造函數(shù)時(shí),子類的構(gòu)造函數(shù) 必須通過(guò)this或者super語(yǔ)句指定要訪問(wèn)的構(gòu)造函數(shù)。
2. 覆蓋時(shí),子類方法權(quán)限一定要大于等于父類方法權(quán)限
靜態(tài)只能覆蓋靜態(tài)。
父類中的私有方法不可以被覆蓋。
3.被final修飾的類是一個(gè)最終類,不可以被繼承。
被final修飾的方法是一個(gè)最終方法,不可以被覆蓋。
被final修飾的變量是一個(gè)常量,只能賦值一次
內(nèi)部類只能訪問(wèn)被final修飾的局部變量。
4. 繼承與重載:一是子類與父類的關(guān)系,二是重載方法的調(diào)用問(wèn)題。
3.多態(tài)
方法的重寫、重載與動(dòng)態(tài)連接構(gòu)成多態(tài)性。Java只允許單繼承,這樣做雖然保證了繼承關(guān)系的簡(jiǎn)單明了,但是功能上有很大的限制,所以,Java引入了多態(tài)性的概念。此外,抽象類和接口也是解決單繼承規(guī)定限制的重要手段。同時(shí),多態(tài)也是面向?qū)ο缶幊痰木杷凇?/p>
多態(tài)性:發(fā)送消息給某個(gè)對(duì)象,讓該對(duì)象自行決定響應(yīng)何種行為。
通過(guò)將子類對(duì)象引用賦值給超類對(duì)象引用變量來(lái)實(shí)現(xiàn)動(dòng)態(tài)方法調(diào)用。
java 的這種機(jī)制遵循一個(gè)原則:當(dāng)超類對(duì)象引用變量引用子類對(duì)象時(shí),被引用對(duì)象的類型而不是引用變量的類型決定了調(diào)用誰(shuí)的成員方法,但是這個(gè)被調(diào)用的方法必須是在超類中定義過(guò)的,也就是說(shuō)被子類覆蓋的方法。
1. 如果a是類A的一個(gè)引用,那么,a可以指向類A的一個(gè)實(shí)例,或者說(shuō)指向類A的一個(gè)子類。
2. 如果a是接口A的一個(gè)引用,那么,a必須指向?qū)崿F(xiàn)了接口A的一個(gè)類的實(shí)例。
要理解多態(tài)性,首先要知道什么是“向上轉(zhuǎn)型”。
子類Cat繼承了Animal類,那么后者就是前者是父類。
Cat c = new Cat();//實(shí)例化一個(gè)Cat的對(duì)象,
Animal a = new Cat();//定義了一個(gè)Animal類型的引用,指向新建的Cat類型的對(duì)象
由于Cat是繼承自它的父類Animal,所以Animal類型的引用是可以指向Cat類型的對(duì)象的。那么這樣做的什么意義是:因?yàn)樽宇愂菍?duì)父類的一個(gè)改進(jìn)和擴(kuò)充,所以一般子類在功能上較父類更強(qiáng)大,屬性較父類更獨(dú)特,
定義一個(gè)父類類型的引用指向一個(gè)子類的對(duì)象既可以使用子類強(qiáng)大的功能,又可以抽取父類的共性。
所以,父類類型的引用可以調(diào)用父類中定義的所有屬性和方法,但是對(duì)于子類中定義而父類中沒(méi)有的方法,它是無(wú)可奈何的;
同時(shí),父類中的一個(gè)方法只有在在父類中定義而在子類中沒(méi)有重寫的情況下,才可以被父類類型的引用調(diào)用;
對(duì)于父類中定義的方法,如果子類中重寫了該方法,那么父類類型的引用將會(huì)調(diào)用子類中的這個(gè)方法,這就是動(dòng)態(tài)連接。
如這段程序:
class Father{
public void func1(){
func2();
}
public void func2(){//這是父類中的func2()方法,因?yàn)橄旅娴淖宇愔兄貙懥嗽摲椒?/p>
//所以在父類類型的引用中調(diào)用時(shí),這個(gè)方法將不再有效
//取而代之的是將調(diào)用子類中重寫的func2()方法
System.out.println("AAA");
}
}
class Child extends Father{
//func1(int i)是對(duì)func1()方法的一個(gè)重載
//由于在父類中沒(méi)有定義這個(gè)方法,所以它不能被父類類型的引用調(diào)用
//所以在下面的main方法中child.func1(68)是不對(duì)的
public void func1(int i){
System.out.println("BBB");
}
//func2()重寫了父類Father中的func2()方法
//如果父類類型的引用中調(diào)用了func2()方法,那么必然是子類中重寫的這個(gè)方法
public void func2(){
System.out.println("CCC");
}
}
public class PolymorphismTest {
public static void main(String[] args) {
Father child = new Child();
child.func1();//打印結(jié)果將會(huì)是什么?
}
}
這是個(gè)很典型的多態(tài)的例子。子類Child繼承了父類Father,并重載了父類的func1()方法,重寫了父類的func2()方法。重載后的func1(int i)和func1()不再是同一個(gè)方法,由于父類中沒(méi)有func1(int i),那么,父類類型的引用child就不能調(diào)用func1(int i)方法。而子類重寫了func2()方法,那么父類類型的引用child在調(diào)用該方法時(shí)將會(huì)調(diào)用子類中重寫的func2()。
所以程序運(yùn)行結(jié)果應(yīng)該是“CCC”。
實(shí)現(xiàn)多態(tài),有二種方式,覆蓋(override),重載(overload)。
覆蓋,是指子類重新定義父類的虛函數(shù)的做法。它是覆蓋了一個(gè)方法并且對(duì)其重寫,以求達(dá)到不同的作用。在覆蓋要注意以下的幾點(diǎn):
1、覆蓋的方法的標(biāo)志必須要和被覆蓋的方法的標(biāo)志完全匹配,才能達(dá)到覆蓋的效果;
2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
3、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;
4、被覆蓋的方法不能為private,否則在其子類中只是新定義了一個(gè)方法,并沒(méi)有對(duì)其進(jìn)行覆蓋。
重載,是指允許存在多個(gè)同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個(gè)數(shù)不同,或許參數(shù)類型不同,或許兩者都不同)。它是指我們可以定義一些名稱相同的方法,通過(guò)定義不同的輸入?yún)?shù)來(lái)區(qū)分這些方法,然后再調(diào)用時(shí),在使用重載要注意以下的幾點(diǎn):
1、在使用重載時(shí)只能通過(guò)不同的參數(shù)樣式。例如,不同的參數(shù)類型,不同的參數(shù)個(gè)數(shù),不同的參數(shù)順序(當(dāng)然,同一方法內(nèi)的幾個(gè)參數(shù)類型必須不一樣,例如可以是fun(int,float),但是不能為fun(int,int));
2、不能通過(guò)訪問(wèn)權(quán)限、返回類型、拋出的異常進(jìn)行重載;
3、方法的異常類型和數(shù)目不會(huì)對(duì)重載造成影響;
4、對(duì)于繼承來(lái)說(shuō),如果某一方法在父類中是訪問(wèn)權(quán)限是priavte,那么就不能在子類對(duì)其進(jìn)行重載,如果定義的話,也只是定義了一個(gè)新方法,而不會(huì)達(dá)到重載的效果。
多態(tài)也有弊端:當(dāng)父類引用指向子類對(duì)象時(shí),雖然提高了擴(kuò)展性,但是只能訪問(wèn)父類中具備的方法,不可以訪問(wèn)子類中特有的方法。(前期不能使用后期產(chǎn)生的功能,即訪問(wèn)的局限性)
【Java語(yǔ)言中面向?qū)ο蟮奶匦浴肯嚓P(guān)文章:
Java面向?qū)ο笤O(shè)計(jì)的經(jīng)驗(yàn)原則10-12
2017年Java面向?qū)ο竺嬖囶}05-19
java程序10個(gè)面向?qū)ο笤O(shè)計(jì)原則05-25