Java語言中面向對象的特性

Java自動的“無用單元收集”預防存儲漏泄和其它有關動態存儲分配和解除分配的有害錯誤。Java解釋程序也執行許多運行時的檢查,諸如驗證所有數組和串訪問是否在界限之內。下面是小編整理的關於Java語言中面向對象的特性,希望大家認真閱讀!

Java語言中面向對象的特性

  Java面向對象

面向對象是一種程序設計方法,或者是程序設計規範,其基本思想是使用對象、類、繼承、封裝、多態等基本概念來進行程序設計。 面向對象是一種符合人們思考習慣的思想,可以將複雜的事情簡單化,將程序員從執行者轉換成了指揮者

完成需求時:

• 先要去找具有所需的功能的對象來用。

• 如果該對象不存在,那麼創建一個具有所需功能的對象。

• 這樣簡化開發並提高代碼的複用。

面向對象的開發過程其實就是不斷的創建對象,使用對象,指揮對象做事情。設計的過程其實就是在管理和維護對象之間的關係。

面向對象的特徵:

• 封裝(encapsulation)

• 繼承(inheritance)

• 多態(polymorphism)

  1.封裝

概念:是指隱藏對象的屬性和實現細節,僅對外提供公共訪問方式。

好處:• 將變化隔離。• 便於使用。• 提高重用性。• 提高安全性。

封裝原則:

• 將不需要對外提供的內容都隱藏起來。

• 把屬性都隱藏,提供公共方法對其訪問。

Java中可以通過對類的成員設置一定的訪問權限,實現類中成員的信息隱藏。

private:類中限定爲private的成員,只能被這個類本身訪問。如果一個類的構造方法聲明爲private,則其它類不能生成該類的一個實例。

default:類中不加任何訪問權限限定的成員屬於缺省的(default)訪問狀態,可以被這個類本身和同一個包中的類所訪問。

protected:類中限定爲protected的成員,可以被這個類本身、它的子類(包括同一個包中以及不同包中的子類)和同一個包中的所有其他的類訪問。

public:類中限定爲public的成員,可以被所有的類訪問。

如下面的這個student類,就是使用了封裝,將類中的屬性name 、age和score私有化,使外部不能直接訪問他們,只能通過public類型的對他們方法進行操作。

class Student {

private String name;//聲明屬性 ,並設爲私有類型,起到封裝的作用

private int age;

private int score;

public Student(String name,int age ,int score) { //構造函數,分別給name、age、score賦值

= name;// :this代本類對象的引用

= age;

e= score;

}

public String getName() { //設置getter方法,因爲變量設爲了私有,對象無法訪問類中的屬性,需要用getter方法獲取變量

return name;

}

public void setName(String name) { //設置setter方法,因爲變量設爲了私有,對象無法訪問類中的屬性,需要用setter方法給變量賦值

= name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

= age;

}

public int getScorre() {

return score;

}

public void setScorre(int score) {

e = score;

}

}

  2.繼承

繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。對象的一個新類可以從現有的類中派生,這個過程稱爲類繼承。

新類繼承了原始類的特性,新類稱爲原始類的派生類(子類),而原始類稱爲新類的基類(父類)。派生類可以從它的基類那裏繼承方法和實例變量,並且類可以修改或增加新的方法使之更適合特殊的需要。

子類可以直接訪問父類中的非私有的屬性和行爲。通過 extends 關鍵字讓類與類之間產生繼承關係。如下:class SubDemo extends Demo{}

繼承提高了代碼的複用性。

繼承的出現讓類與類之間產生了關係,提供了多態的前提

繼承的特點:

Java只支持單繼承,不支持多繼承。

• 一個類只能有一個父類,不可以有多個父類。

• class SubDemo extends Demo{} //這是對的

• class SubDemo extends Demo1,Demo2...//這是錯的

Java支持多層繼承(繼承體系)

• class A{}

• class B extends A{}

• class C extends B{}

定義繼承需要注意:

• 不要僅爲了獲取其他類中某個功能而去繼承

• 類與類之間要有所屬關係,xx1是xx2的一種。

如:

class Ren { //父類

int age=20;

String name="wk";

public void show() {

tln("姓名:"+name+" 年齡:"+age);

}

}

class Sudents extends Ren {//子類Sudents繼承了父類Ren

int score=90;//增加了新的屬性

int age= +1;//使用super標記父類中的元素,修改了Ren中age的值

public void show() {//重寫了父類中的方法( 覆蓋時,子類方法權限一定要大於等於父類方法權限,靜態只能覆蓋靜態。)

tln("姓名:"+name+" 年齡:"+age+" 分數:"+ score);// Sudents繼承了Ren,所以Ren中的屬性name和age在Sudents可以直接使用

}

}

public class Preson {

public static void main(String[] args) {

Ren ren = new Ren();//聲明一個Ren對象

Sudents sudents = new Sudents();//聲明一個Sudents對象

();

();

}

}

程序運行結果是:

super和this的用法相同:this代表本類應用 ;super代表父類引用 。當子父類出現同名成員時,可以用super進行區分 ,子類要調用父類構造函數時,可以使用super語句。

在子類覆蓋方法中,繼續使用被覆蓋的方法可以通過super.函數名獲取。

注意:

1. 子類中所有的構造函數默認都會訪問父類中空參數的構造函數,因爲每一個構造函數的第一行都有一條默認的語句 super();子類會具備父類中的數據,所以要先明確父類是如何對這些數據初始化的。當父類中沒有空參數的構造函數時,子類的構造函數 必須通過this或者super語句指定要訪問的構造函數。

2. 覆蓋時,子類方法權限一定要大於等於父類方法權限

靜態只能覆蓋靜態。

父類中的私有方法不可以被覆蓋。

3.被final修飾的類是一個最終類,不可以被繼承。

被final修飾的方法是一個最終方法,不可以被覆蓋。

被final修飾的變量是一個常量,只能賦值一次

內部類只能訪問被final修飾的局部變量。

4. 繼承與重載:一是子類與父類的關係,二是重載方法的調用問題。

  3.多態

方法的重寫、重載與動態連接構成多態性。Java只允許單繼承,這樣做雖然保證了繼承關係的簡單明瞭,但是功能上有很大的限制,所以,Java引入了多態性的`概念。此外,抽象類和接口也是解決單繼承規定限制的重要手段。同時,多態也是面向對象編程的精髓所在。

多態性:發送消息給某個對象,讓該對象自行決定響應何種行爲。

通過將子類對象引用賦值給超類對象引用變量來實現動態方法調用。

java 的這種機制遵循一個原則:當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。

1. 如果a是類A的一個引用,那麼,a可以指向類A的一個實例,或者說指向類A的一個子類。

2. 如果a是接口A的一個引用,那麼,a必須指向實現了接口A的一個類的實例。

要理解多態性,首先要知道什麼是“向上轉型”。

子類Cat繼承了Animal類,那麼後者就是前者是父類。

Cat c = new Cat();//實例化一個Cat的對象,

Animal a = new Cat();//定義了一個Animal類型的引用,指向新建的Cat類型的對象

由於Cat是繼承自它的父類Animal,所以Animal類型的引用是可以指向Cat類型的對象的。那麼這樣做的什麼意義是:因爲子類是對父類的一個改進和擴充,所以一般子類在功能上較父類更強大,屬性較父類更獨特,

定義一個父類類型的引用指向一個子類的對象既可以使用子類強大的功能,又可以抽取父類的共性。

所以,父類類型的引用可以調用父類中定義的所有屬性和方法,但是對於子類中定義而父類中沒有的方法,它是無可奈何的;

同時,父類中的一個方法只有在在父類中定義而在子類中沒有重寫的情況下,纔可以被父類類型的引用調用;

對於父類中定義的方法,如果子類中重寫了該方法,那麼父類類型的引用將會調用子類中的這個方法,這就是動態連接。

如這段程序:

class Father{

public void func1(){

func2();

}

public void func2(){//這是父類中的func2()方法,因爲下面的子類中重寫了該方法

//所以在父類類型的引用中調用時,這個方法將不再有效

//取而代之的是將調用子類中重寫的func2()方法

tln("AAA");

}

}

class Child extends Father{

//func1(int i)是對func1()方法的一個重載

//由於在父類中沒有定義這個方法,所以它不能被父類類型的引用調用

//所以在下面的main方法中1(68)是不對的

public void func1(int i){

tln("BBB");

}

//func2()重寫了父類Father中的func2()方法

//如果父類類型的引用中調用了func2()方法,那麼必然是子類中重寫的這個方法

public void func2(){

tln("CCC");

}

}

public class PolymorphismTest {

public static void main(String[] args) {

Father child = new Child();

1();//打印結果將會是什麼?

}

}

這是個很典型的多態的例子。子類Child繼承了父類Father,並重載了父類的func1()方法,重寫了父類的func2()方法。重載後的func1(int i)和func1()不再是同一個方法,由於父類中沒有func1(int i),那麼,父類類型的引用child就不能調用func1(int i)方法。而子類重寫了func2()方法,那麼父類類型的引用child在調用該方法時將會調用子類中重寫的func2()。

所以程序運行結果應該是“CCC”。

實現多態,有二種方式,覆蓋(override),重載(overload)。

覆蓋,是指子類重新定義父類的虛函數的做法。它是覆蓋了一個方法並且對其重寫,以求達到不同的作用。在覆蓋要注意以下的幾點:

1、覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配,才能達到覆蓋的效果;

2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;

3、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;

4、被覆蓋的方法不能爲private,否則在其子類中只是新定義了一個方法,並沒有對其進行覆蓋。

重載,是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)。它是指我們可以定義一些名稱相同的方法,通過定義不同的輸入參數來區分這些方法,然後再調用時,在使用重載要注意以下的幾點:

1、在使用重載時只能通過不同的參數樣式。例如,不同的參數類型,不同的參數個數,不同的參數順序(當然,同一方法內的幾個參數類型必須不一樣,例如可以是fun(int,float),但是不能爲fun(int,int));

2、不能通過訪問權限、返回類型、拋出的異常進行重載;

3、方法的異常類型和數目不會對重載造成影響;

4、對於繼承來說,如果某一方法在父類中是訪問權限是priavte,那麼就不能在子類對其進行重載,如果定義的話,也只是定義了一個新方法,而不會達到重載的效果。

多態也有弊端:當父類引用指向子類對象時,雖然提高了擴展性,但是隻能訪問父類中具備的方法,不可以訪問子類中特有的方法。(前期不能使用後期產生的功能,即訪問的侷限性)