如今通常的語言都支持面向對象,而java更是將其作到很過度的地步,java是強制使用面向對象的寫法,簡單的寫一個Hello Word都必須使用面向對象,這也是當初我很反感它的一點,固然如今也是很不喜歡它這一點。可是不得不說它設計的很優秀也很流行。
java
面向對象通常是將一些獨立有類似功能的模塊封裝起來組成一個類,而後調用者沒必要關注實現細節而只須要關注調用某個類方法便可。面向對象簡化了程序設計。與之相對應的是面向過程,而C就是典型的面向過程的程序設計語言。c++
面向對象通常有3種特性:封裝、繼承、多態。此次主要講述的是java中的封裝型。數據庫
在java中類的定義與C++中類的定義相似,只是在java中每定義一個方法或者成員變量都須要在前面添加一個訪問的權限修飾符,好比下面的定義編程
class Student { private String name; private int age; public Student(){ } public Student(String name, int age){ this.name = name; this.age = age; } public int getAge(){ return this.age; } public String getName(){ return this.name; } public void setAge(int age){ this.age = age; } public void setName(String name){ this.name = name; } }
而C++中只須要將具備相同訪問屬性的放到一塊,用一次修飾符便可。好比上面java代碼對應的C++代碼以下:安全
class Student { private: string name; int age; public: Student(){ } Student(string name, int age){ this->name = name; this->age = age; } int getAge(){ return this->age; } String getName(){ return this->name; } void setAge(int age){ this->age = age; } void setName(String name){ this->name = name; } }
在C++中類中的成員若是不給訪問權限,默認是private, 而java中默認的訪問權限是friendly,可是這個friendly在java中並非關鍵字,並且java中的public、private、protected 都必須明確指定,在java中這些關鍵字對應的訪問權限以下:多線程
訪問權限 | 當前類 | 同一個package | 子孫類 | 其餘package |
---|---|---|---|---|
public | yes | yes | yes | yes |
protected | yes | yes | yes | no |
firendly | yes | yes | no | no |
private | yes | no | no | no |
從上一個表中能夠看到public 對於類成員的訪問徹底沒有限制、而protected僅僅保護類成員不被其餘包訪問,默認的friendly只容許同一個包或者同一個類的成員訪問,最後的private僅容許同一個類的成員訪問,它們的訪問權限是遞增的,也就是public > protected > friendly > private編程語言
面向對象的封裝性就體如今僅僅容許經過類方法訪問類成員。這有助於保護類成員不被其餘代碼隨意的篡改,並且若是類成員在進行修改時若是會涉及到其餘變化,咱們只須要在get/set方法中控制便可,不須要外部使用人員瞭解這個細節。函數
假設如今有一個教務系統,裏面須要存儲學生的信息,那麼若是不採用封裝的方式而直接在類代碼外進行訪問的話,並且成員被訪問的位置較多,一旦發現數據庫中存儲的數據發生錯誤,那麼將沒法肯定是在哪給定了錯誤的值,並且要對輸入值進行判斷的時候,每一個被訪問的位置都要添加這些判斷的代碼,修改量較大,並且沒法保證每一個位置都正常修改了。若是後續業務邏輯修改,那麼這些工做又得從新作一遍。若是咱們將成員變量使用set和get方法進行封裝,查看數據錯誤的問題只須要關注get/set方法,並且業務邏輯變動時只須要修改get/set方法。這點體現了封裝性對數據的保護做用。this
在假設這裏咱們採用多線程的方式來訪問數據,那麼爲了保護數據,就須要添加相應的同步代碼,若是直接訪問,那麼每當訪問一次數據,就須要添加保護代碼。這樣就爲使用人員添加了沒必要要的麻煩,若是咱們將這些進行封裝,而後告訴使用人員,這個類是線程安全的,那麼使用人員直接調用而不用管其中的細節,後續若是咱們換一種同步的方式,也不影響其餘人的使用。線程
C++中this關鍵字就是一個指針,經過eax寄存器傳入到類的成員函數中,在成員函數中,經過this + 偏移地址來定位類中全部成員。而java中this除了能像c++中那樣用於表示訪問類成員外,還有另外兩個做用
class Student { private String name; private int age; public Student(){ } public Student(String name){ this(); //調用無參構造 this.name = name; } public Student(String name, int age){ this(name); // 調用有一個參數的構造方法 this.age = age; } public int getAge(){ return this.age; } public String getName(){ return this.name; } public void setAge(int age){ this.age = age; } public void setName(String name){ this.name = name; } }
class Student { private String name; private int age; public Student(){ } public Student(String name){ this(); //調用無參構造 this.name = name; } public Student(String name, int age){ this(name); // 調用有一個參數的構造方法 this.age = age; } public int getAge(){ return this.age; } public String getName(){ return this.name; } public void setAge(int age){ this.age = age; } public void setName(String name){ this.name = name; } public boolean compare(Student stu){ return this == stu; //這裏簡單實用兩者的地址進行比較 } }
java中的構造函數與C++中的相同。是在new對象的時候調用的函數。注意這裏只是說它在new的時候調用的函數,並非在使用類的時候第一次調用的函數。
Java 中的構造方法必須與該類具備相同的名字,而且沒有方法的返回類型。每一個類至少有一個構造方法。若是不寫一個構造方法,Java 編程語言將提供一個默認的,該構造方法沒有參數,並且方法體爲空。若是一個類中已經定義了構造方法則系統再也不提供默認的構造方法。
java中不能直接訪問內存,雖然它的類都是new出來的,可是資源的回收由垃圾回收機制來完成,那麼它有析構函數嗎?答案是確定的,java中也是有析構函數的。在C++中進行棧資源回收或者手工調用delete的時候纔會進行析構函數的調用。而在java中,當垃圾回收器將要釋放無用對象的內存時,先調用該對象的finalize()方法。這個finalize方法就是類的析構函數,這個方法是由Object這個基類提供的一個方法,Object子類能夠選擇重寫它或者就用默認的。這個方法嚴格上應該是一個接口函數,與C++的析構並不相同。
Java 虛擬機的垃圾回收操做對程序徹底是透明的,所以程序沒法預料某個無用對象的finalize()方法什麼時候被調用。
上面說構造函數並非使用類時第一個調用的函數,第一個調用的函數應該是靜態代碼塊(這個代碼塊應該不能被稱之爲函數)。靜態代碼塊是第一次使用類的時候被調用,並且僅僅只調用這一次。它的定義以下:
class Student{ staic { System.out.println("調用靜態代碼塊"); } }