您好,登錄后才能下訂單哦!
本篇內容介紹了“java面向對象的三大特征是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
我們程序設計追求“高內聚,低耦合”
高內聚:類的內部數據操作細節自己完成,不允許外部干涉
低耦合:僅對外暴露少量的方法用于使用。
隱藏對象內部的復雜性,只對外公開簡單的接口。便于外界調用,從而提高系統的可擴展性、可維護性。通俗的說,把該隱藏的隱藏起來,該暴露的暴露岀來。這就是封裝性的設計思想。
當我們創建一個類的對象以后,我們可以通過"對象.屬性"的方式,對對象的屬性進行賦值。這里,賦值操作要受到屬性的數據類型和存儲范圍的制約。除此之外,沒其他制約條件。但是,在實際問題中,我們往往需要給屬性賦值加入額外的限制條件。這個條件就不能在屬性聲明時體現,我們只能通過方法進行限制條件的添加。(比如:setName()同時,我們需要避免用戶再使用"對象.屬性"的方式對屬性進行賦值。則需要將屬性聲明為私有的(private)。此時,針對于屬性就體現了封裝性。
體現一:
將類的屬性xxx私化(private),同時,提供公共的(public)方法來獲取(getXxx)和設置(setXxx)此屬性的值
private double radius; public void setRadius(double radius){ this.radius = radius; } public double getRadius(){ return radius; }
體現二:不對外暴露的私有的方法
體現三:單例模式(將構造器私有化)
體現四:如果不希望類在包外被調用,可以將類設置為缺省的。
通過對不同的方法屬性設置不同的權限修飾符來達到對類進行封裝的目的。
權限從小到大順序為:private < 缺省 < protected < public
具體的修飾范圍:
修飾符 | 類內部 | 同一個包 | 不同包的子類 | 同一個工程 |
---|---|---|---|---|
private | Yes | |||
(缺省) | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
權限修飾符可用來修飾的結構說明:
4種權限都可以用來修飾類的內部結構:屬性、方法、構造器、內部類
修飾類,只能使用:缺省、public
減少了代碼的冗余,提高了代碼的復用性
便于功能的擴展
為之后多態性的使用,提供了前提
class A extends B{} * A:子類、派生類、subclass * B:父類、超類、基類、superclass
判斷是否要進行繼承:A is a B,若成立,則B繼承A
子類A繼承父類B以后,子類A中就獲取了父類B中聲明的所有的屬性和方法。特別的,父類中聲明為private的屬性或方法,子類繼承父類以后,仍然認為獲取了父類中私的結構。只因為封裝性的影響,使得子類不能直接調用父類的結構而已。
子類繼承父類以后,還可以聲明自己特有的屬性或方法:實現功能的拓展。子類和父類的關系,不同于子集和集合的關系。
一個類可以被多個子類繼承。
Java中類的單繼承性:一個類只能有一個父類
子父類是相對的概念。
子類直接繼承的父類,稱為:直接父類。間接繼承的父類稱為:間接父類
子類繼承父類以后,就獲取了直接父類以及所間接父類中聲明的屬性和方法
是Java中所有類的父類,類似于二叉樹中的根節點,定義了一些通用的方法。
如果我們沒顯式的聲明一個類的父類的話,則此類繼承于java.lang.Object類
所的java類(除java.lang.Object類之外都直接或間接的繼承于java.lang.Object類
意味著,所的java類具有java.lang.Object類聲明的功能。
java.lang.Object類中定義的一些方法
方法名 | 類型 | 描述 |
---|---|---|
public Object() | 構造方法 | 構造器 |
public boolean equals( Object obj) | 普通方法 | 對象比較 |
public int hashCode() | 普通方法 | 獲取Hash碼 |
public String toString() | 普通方法 | 對象打印時調用 |
Object類是所Java類的根父類
如果在類的聲明中未使用extends關鍵字指明其父類,則默認父類為java.lang.Object類
Object類中的功能(屬性、方法)就具通用性。
屬性:無
方法:equals() / toString() / getClass() /hashCode() / clone() / finalize()
wait() 、 notify()、notifyAll()
Object類只聲明了一個空參的構造器
數組也作為 Object類的子類出現,可以調用 Object類中聲明的方法
是一個方法,而非運算符
只能適用于引用數據類型
public boolean equals(Object obj) { return (this == obj); }
使用說明:
Object類中定義的equals()和==的作用是相同的:比較兩個對象的地址值是否相同.即兩個引用是否指向同一個對象實體
像==String、Date、File、包裝類==等都重寫了Object類中的equals()方法。==重寫==以后,比較的不是兩個引用的地址是否相同,而是==比較兩個對象的"實體內容"是否相同==。
通常情況下,我們自定義的類如果使用equals()的話,也通常是比較兩個對象的"實體內容"是否相同。那么,我們就需要對Object類中的equals()進行重寫.
重寫的原則:比較兩個對象的實體內容是否相同.
手動重寫舉例:
class User{ String name; int age; //重寫其equals()方法 public boolean equals(Object obj){ if(obj == this){//判斷形參和比較對象的引用地址是否相同,相同直接返回true return true; } if(obj instanceof User){ User u = (User)obj; return this.age == u.age && this.name.equals(u.name); } return false; } }
自動生成的,自動生成快捷鍵ctrl+alt+S,選擇自動生成hashCode和equals方法
自動生成的代碼:
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true;
回顧 == 運算符的使用:
== :運算符
可以使用在基本數據類型變量和引用數據類型變量中
如果比較的是基本數據類型變量:
比較兩個變量保存的數據是否相等。(不一定類型要相同)
如果比較的是引用數據類型變量:
比較兩個對象的地址值是否相同,即兩個引用是否指向同一個對象實體
使用說明
== 符號使用時,必須保證符號左右兩邊的變量類型一致。
基本數據類型用==,引用數據類型用equals
toString()的使用:
當我們輸出一個對象的引用時,實際上就是調用當前對象的toString()方法
Object類中toString()的定義:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
像String、Date、File、包裝類等都重寫了Object類中的toString()方法。使得在調用對象的toString()時,返回"實體內容"信息。
自定義類也可以重寫toString()方法,當調用此方法時,返回對象的"實體內容"
重寫toString()
//自動實現 @Override public String toString() { return "Customer [name=" + name + ", age=" + age + "]"; }
子類繼承父類以后,就獲取了父類中聲明的屬性或方法。 創建子類的對象,在堆空間中,就會加載所父類中聲明的屬性。
當我們通過子類的構造器創建子類對象時,我們一定會直接或間接的調用其父類的構造器,進而調用父類的父類的構造器,...直到調用了java.lang.Object類中空參的構造器為止。正因為加載過所的父類的結構,所以才可以看到內存中父類中的結構,子類對象才可以考慮進行調用。
雖然創建子類對象時,調用了父類的構造器,但是自始至終就創建過一個對象,即為new的子類對象。
可以理解為一個事物的多種形態。比如數據庫的連接方式,我們定義好了數據庫的連接,也規定了連接時的步驟,但是我們并不知道用戶會采用什么數據庫,在沒有多態以前我們只能針對不同的數據庫寫不同的連接方法,而有了多態以后我們只需要定義好數據庫的類并書寫好連接方法,讓所有的數據庫繼承數據庫類并重寫數據庫連接方法。
這樣我們在調用的時候只需要通過聲明數據庫類并指向數據庫的子類的方式,**(即數據庫類的引用指向繼承了數據庫類的具體實現類的對象)**就可以進行數據庫連接。而不是需要針對不同的數據庫書寫不同的連接方式。
對象的多態性:父類的引用指向子類的對象(或子類的對象賦給父類的引用)
編譯時和運行時類型不一致,產生了多態
代碼舉例:
Person p = new Man(); Object obj = new Date();
有了對象的多態性以后,我們在編譯期,只能調用父類中聲明的方法,但在運行期,我們實際執行的是子類重寫父類的方法。
總結:編譯,看左邊;運行,看右邊。
對象的多態:在Java中,子類的對象可以替代父類的對象使用
一個變量只能有一種確定的數據類型
一個引用類型變量可能指向(引用)多種不同類型的對象
① 類的繼承關系 ② 方法的重寫
舉例一: public void func(Animal animal){//Animal animal = new Dog(); animal.eat(); animal.shout(); } 舉例二: public void method(Object obj){ } 舉例三: class Driver{ public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection(); //規范的步驟去操作數據 // conn.method1(); // conn.method2(); // conn.method3(); } }
對象的多態性,只適用于方法,不適用于屬性(編譯和運行都看左邊)
個引用類型變量如果聲明為父類的類型,但實際引用的是子類對象,那么該變量就==不能==再訪問子類中添加的屬性和方法
多態的作用:提高了代碼的通用性,常稱作接口重用
使用前提:①需要存在繼承或者實現關系 ②有方法的重寫
成員方法:
編譯時:要查看引用變量所聲明的類中是否有所調用的方法
運行時:調用實際new的對象所屬的類中的重寫方法
成員變量:不具備多態性,只看引用變量所聲明的類
向上轉型:多態
有了對象的多態性以后,內存中實際上是加載了子類特有的屬性和方法的,但是由于變量聲明為父類類型,導致編譯時,只能調用父類中聲明的屬性和方法。子類特有的屬性和方法不能調用。如何才能調用子類特的屬性和方法?使用向下轉型。
使用強制類型轉換符:()
Person p = new Man(); Man m1=(Man)p2;//向下轉型
① 使用強轉時,可能出現ClassCastException的異常。
② 為了避免在向下轉型時出現ClassCastException的異常,我們在向下轉型之前,先進行instanceof的判斷,一旦返回true,就進行向下轉型。如果返回false,不進行向下轉型。
③ 只有對象A是B的子類實例化對象或者在下層的子類,才能向下轉型
① a instanceof A:==判斷對象a==是否是==類A的實例==。如果是,返回true;如果不是,返回false。
② 如果 a instanceof A返回true,則 a instanceof B也返回true.其中,類B是類A的父類。
③ 要求a所屬的類與類A必須是子類和父類的關系,否則編譯錯誤。
p instanceif Man//左邊是變量名,右邊是類的類型
1.談談你對多態性的理解?
實現代碼的通用性。
舉例:
Object類中定義的public boolean equals(Object obj){ }
JDBC:使用java程序操作(獲取數據庫連接、CRUD)數據庫(MySQL、Oracle、DB2、SQL Server)
抽象類、接口的使用肯定體現了多態性。(抽象類、接口不能實例化)
**2.多態是編譯時行為還是運行時行為?**運行時行為
class Base { int count = 10; public void display() { System.out.println(this.count); } } class Sub extends Base { int count = 20; public void display() { System.out.println(this.count); } } public class FieldMethodTest { public static void main(String[] args) { Sub s = new Sub(); System.out.println(s.count);//20 s.display();//20 Base b = s;//多態性 //==:對于引用數據類型來講,比較的是兩個引用數據類型變量的地址值是否相同 System.out.println(b == s);//true System.out.println(b.count);//10 b.display();//20 } }
若子類重寫了父類方法,就意味著子類里面定義的方法徹底覆蓋了父類里的同名方法,系統將不可能把父類里的方法轉移到子類中:編譯看左邊,運行看右邊
對于實例變量則不存在這樣的現象,即使子類里定義了與父類完全相同的實例變量,這個實例變量依然不可能覆蓋父類中定義的實例變量:編譯運行都看左邊
“java面向對象的三大特征是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。