Java探索之旅(11)——抽象类与接口
1.Java數(shù)據(jù)類型
? ? ? ?不可變類,是指當(dāng)創(chuàng)建了這個(gè)類的實(shí)例后,就不允許修改它的屬性值。 它包括: ? ? ? ??Primitive變量:boolean,byte, char, double ,float, integer, long, short ? ? ? ? JDK不可變類:Boolean, Byte, Character, Double, Float, Integer, Long, Short, String (java.lang包中) ? ? ??可變類,是當(dāng)你獲得這個(gè)類的一個(gè)實(shí)例引用時(shí),你可以改變這個(gè)實(shí)例的內(nèi)容。 可變類對(duì)象間用“=”賦值,則會(huì)是使兩個(gè)對(duì)象實(shí)際上會(huì)引用同一個(gè)實(shí)例。所以,只有實(shí)現(xiàn)深度clone才能使可變類對(duì)象的修改不影響原始對(duì)象的值。? ? ??對(duì)于不可變類,可變類的特性也有意義,有的時(shí)候我們不希望重復(fù)創(chuàng)建相同的內(nèi)容的實(shí)例。因此,我們也可以利用不可變類獲得實(shí)例緩存。如:
? Integer a=Integer.valueOf(10); Integer b= Integer.valueOf(10);? ? 只會(huì)在第一次創(chuàng)建取值為10的Integer對(duì)象。也就是說(shuō)a和b指向同一處內(nèi)存上的內(nèi)容。
2.抽象類
? ? ?繼承層次結(jié)構(gòu)中。父類通用而不明確,子類越來(lái)越明確和具體。接口是定義多個(gè)類的共同行為。
? ? ?抽象關(guān)鍵字abstract,位置緊隨訪問(wèn)修飾符(public,protected,private)之后。
? ? ?抽象類的構(gòu)造函數(shù)一律定義為protected。抽象方法只有定義沒(méi)有實(shí)現(xiàn)(一般定義為public,且抽象方法禁止定義為靜態(tài)方法)。
? ? ?包含抽象方法的類必須定義為抽象類。抽象類不一定需要包含抽象方法。
? ? ?若子類沒(méi)有實(shí)現(xiàn)父類的抽象方法。子類仍需要定義為抽象類。即,抽象類派生出的非抽象子類,必須實(shí)現(xiàn)所有基類的抽象方法,即使它沒(méi)有使用
? ? ?父類為具體類,子類可以是抽象類。子類可以覆蓋父類的方法并將其定義為抽象方法,當(dāng)然前提是子類定義為抽象類。
? ? ?new無(wú)法作用抽象類創(chuàng)建實(shí)例,但是可以作為一種數(shù)據(jù)類型,創(chuàng)建引用變量(或者引用數(shù)組),然后指向子類對(duì)象。當(dāng)然其引用類型也可以作為函數(shù)參數(shù)。
? ? ?如下定義抽象類Gobject。定義兩個(gè)擴(kuò)展類圓Circle和長(zhǎng)方形rectangle。定義抽象方法getArea()返回面積
package GeometricObject; public abstract class Gobject {private String color="white";private boolean filled;private java.util.Date dateCreated;//時(shí)間類//構(gòu)造函數(shù)必須定義protectedprotected Gobject(){dateCreated=new java.util.Date();}protected Gobject(String s,boolean f){this();filled=f;color=s;}public String toString(){return "Created on:"+dateCreated+"\ncolor:"+color+"\nfilled with?--"+filled;}public void setColor(final String s){color=s;}public String getColor(){return color;}public abstract double getArea();//抽象方法 }//圓類 class Circle extends Gobject implements Comparable,Cloneable{double radius;final static double PI=3.1415;Circle(){radius=1.0;}//隱含調(diào)用super();Circle(double r,String s,boolean f){super(s,f);//調(diào)用父類構(gòu)造函數(shù)radius=r;}public String toString(){return super.toString()+"\nArea--"+getArea();} }//長(zhǎng)方形類 class rectangle extends Gobject implements Comparable,Cloneable{//常用方法,從虛函數(shù)中擴(kuò)展double width,height;rectangle (){width=height=1.0;}//隱含調(diào)用super();rectangle(double w,double h,String s,boolean f){super(s,f);//調(diào)用父類構(gòu)造函數(shù)width=w;height=h;}public double getArea(){return width*height;} }3.接口
? ??類似于類,目的是指明多個(gè)對(duì)象的共同行為。? ??接口類似于抽象類。編譯為單獨(dú)的字節(jié)碼文件。不能使用new創(chuàng)建實(shí)例,但是可以聲明引用變量或者作為類型轉(zhuǎn)換的結(jié)果。
? ??接口僅僅包括常量和抽象方法或者完全為空(所謂的標(biāo)記接口maker interface)。即所有的方法默認(rèn)都是public abstract,所有的變量都是public final static<
? ??接口類定義的常量可以使用“接口名.變量名”訪問(wèn)。
4.可比較接口 Comparable
? ? ? ??Java中的許多類,比如String和Data實(shí)現(xiàn)(implements)了Comparable接口,以比較自然對(duì)象的大小。
? ??接口引用變量可作函數(shù)參數(shù)類型和返回類型。聲明如下:
public interface Comparable //比較接口{int comparaTo(Object o);//判斷當(dāng)前對(duì)象與目標(biāo)對(duì)象的大小} ? ?定義的通用求最大值的Max函數(shù)如下: //通用的求最大值的類 //接口引用作為函數(shù)參數(shù)和返回參數(shù),此時(shí)類似虛函數(shù) public class Max {public static Comparable max(Comparable a,Comparable b){if(a.comparaTo(b)>0)//調(diào)用具體的比較函數(shù)return a;elsereturn b;} }? ?Circle和rectangle分別實(shí)現(xiàn)了該接口,即繼承了接口的抽象方法,并具體實(shí)現(xiàn)。如下:
class Circle extends Gobject implements Comparable,Cloneable{......................public int comparaTo(Object o){//繼承并且實(shí)現(xiàn)camparaTo函數(shù)if(getArea()>((Gobject)o).getArea())//顯式轉(zhuǎn)換return 1;else if(getArea()<((Gobject)o).getArea())return -1;elsereturn 0;}................. }class rectangle extends Gobject implements Comparable,Cloneable{//常用方法,從虛函數(shù)中擴(kuò)展..................public int comparaTo(Object o){//繼承并且實(shí)現(xiàn)camparaTo函數(shù)if(getArea()>((Gobject)o).getArea())return 1;else if(getArea()<((Gobject)o).getArea())return -1;elsereturn 0;}..................... }? ? 利用Max求兩個(gè)圓或者兩個(gè)長(zhǎng)方體最大的面積的代碼片段為
//Comparable 接口//使用通用的Max類,比較任意擴(kuò)展了comparable的對(duì)象Circle[] cp=new Circle[2];cp[0]=new Circle(1.56,"Blue",true);cp[1]=new Circle(3.45,"Green",false);Comparable max=Max.max(cp[0], cp[1]);//接口類型引用System.out.println("The max Area of 2 Circle is "+((Circle)max).getArea());//顯式轉(zhuǎn)換rectangle[] rp=new rectangle[2];rp[0]=new rectangle(1.56,12.0,"Blue",true);rp[1]=new rectangle(3.45,6.7,"Green",false);Comparable max1=Max.max(rp[0], rp[1]);//接口類型引用System.out.println("The max Area of 2 rectangle is "+((rectangle)max1).getArea());//顯式轉(zhuǎn)換? ?由于max輸出的類型為Comparable類型,所以調(diào)用Circle或者rectangle的getArea()函數(shù)必須顯式轉(zhuǎn)換。
5.可克隆接口?Cloneable
? ??該接口為標(biāo)記接口,即無(wú)常量和方法。標(biāo)記用來(lái)表示類擁有某種屬性。定義如下:
public interface Cloneable {} ? ? ?對(duì)于可復(fù)制的類,必須滿足: 實(shí)現(xiàn)Cloneable接口。這樣才有資格調(diào)用Object.clone()方法 覆蓋Object的clone()方法。Object.clone()方法是protected的,覆蓋并改為public? ??Object的clone的行為是最簡(jiǎn)單的。以堆上的內(nèi)存存儲(chǔ)解釋的話(不計(jì)內(nèi)存),對(duì)一個(gè)對(duì)象a的clone就是在堆上分配一個(gè)和a在堆上所占存儲(chǔ)空間一樣大的一塊地方,然后把a(bǔ)的堆內(nèi)存的內(nèi)容按位(bit-wise)復(fù)制到這個(gè)新分配的內(nèi)存。
? ??Primitive數(shù)據(jù)類型(如int,double)為深拷貝,引用類型(包括可變類和不可變類)均為淺拷貝,淺拷貝指拷貝前后引用變量指向同一對(duì)象。深拷貝或者克隆的目的在數(shù)據(jù)前后隔離,默認(rèn)的淺copy不是隔離的——即改變copy的東西,會(huì)影響到原型的內(nèi)部。
? ??改變拷貝對(duì)象的Primitive數(shù)據(jù)值或者不可變類引用變量(如String)的指向?qū)ο?#xff0c;不影響源對(duì)象的對(duì)應(yīng)數(shù)據(jù),即滿足數(shù)據(jù)隔離。前者的原因顯而易見(jiàn),后者的原因是因?yàn)?--不可變類不能通過(guò)【對(duì)象名+"."方法(數(shù)據(jù))】改變數(shù)據(jù)域,只能通過(guò)將其指向其他對(duì)象改變其數(shù)據(jù)域,如此一來(lái),肯定不影響。具體點(diǎn)擊
? ?對(duì)于前面定義的Circle,rectangle類,實(shí)現(xiàn)Coloneable接口如下:
class Circle extends Gobject implements Comparable,Cloneable{......................public Object clone() throws CloneNotSupportedException{return super.clone();}......................}//長(zhǎng)方形類 class rectangle extends Gobject implements Comparable,Cloneable{//常用方法,從虛函數(shù)中擴(kuò)展.......................public Object clone() throws CloneNotSupportedException{return super.clone();}....................... }?注意:? ? ①由于返回的為Object,可能需要顯式轉(zhuǎn)換。
? ? ②使用super.clone()而非this.clone()的原因。Object中的clone執(zhí)行的時(shí)候使用了RTTI(run-time type identification)的機(jī)制,動(dòng)態(tài)得找到目前正在調(diào)用clone方法的reference,根據(jù)它的大小申請(qǐng)內(nèi)存空間,然后進(jìn)行bitwise的復(fù)制,將該對(duì)象的內(nèi)存空間完全復(fù)制到新的空間中去,從而達(dá)到shallowcopy的目的。所以調(diào)用super.clone() 得到的是當(dāng)前調(diào)用類的副本,而不是父類的副本。根本沒(méi)有必用調(diào)用this.clone()
? ? ③如果需要克隆的類引用到了其它的類的對(duì)象,甚至這個(gè)對(duì)象也引用到了別的對(duì)象,那么在必要情況下,你需要將這個(gè)對(duì)象樹(shù)進(jìn)行完整的克隆。如下:
class User implements Cloneable {String name;int age;@Overridepublic User clone() throws CloneNotSupportedException {return (User) super.clone();} }class Account implements Cloneable {User user;long balance;@Overridepublic Account clone() throws CloneNotSupportedException {Account account = (Account) super.clone();if (user != null) {account.user = user.clone();//顯式深拷貝}return account;} }6.抽象類和接口的比較
? ??變量:抽象類無(wú)限制;接口必須為public static final ? ??構(gòu)造方法:抽象類子類經(jīng)過(guò)構(gòu)造鏈調(diào)用構(gòu)造法。接口無(wú)構(gòu)造方法。兩者均不能用new實(shí)例化 ? ??方法:抽象類無(wú)限制;接口必須是public abstract ? ??抽象類只能(被)單一擴(kuò)展;類可以同時(shí)實(shí)現(xiàn)多重接口,接口同時(shí)可以同時(shí)繼承多重接口而不是類。 ? ??所有類有公共根Object;而所有接口沒(méi)有公共接口。 ? ??兩者均可以定義類型,且引用變量可以引用---任何實(shí)現(xiàn)了接口(或抽象類)的對(duì)象。 ? ? 一般而言,父子關(guān)系強(qiáng),使用抽象類;弱使用接口。接口可以定義不相關(guān)類共有的父類型(例如房屋可以比較面積,數(shù)值可以比較大小,使用comparable接口)。抽象類更加使用方便,接口更加靈活。 ? ?注意:?如果向一個(gè)抽象類里加入一個(gè)新的具體方法時(shí),那么它所有的子類都一下子都得到了這個(gè)新方法。接口做不到這一點(diǎn),如果向一個(gè)Java接口里加入一個(gè) 新方法,所有實(shí)現(xiàn)這個(gè)接口的類就無(wú)法成功通過(guò)編譯了,因?yàn)槟惚仨氉屆恳粋€(gè)類都再實(shí)現(xiàn)這個(gè)方法才行,這顯然是Java接口的缺點(diǎn)之一。? ? ? ? ? ? ? ? ?經(jīng)典的使用方法: A extends AbstractB implements interfaceC 詳細(xì)可點(diǎn)擊:Java 接口和抽象類區(qū)別參考: ? ? 1.深入理解java的clone ? ? 2.java.lang.Cloneable接口 ? ? 3.Java的clone機(jī)制及其可變類與不可變類
轉(zhuǎn)載于:https://www.cnblogs.com/engineerLF/p/5393089.html
總結(jié)
以上是生活随笔為你收集整理的Java探索之旅(11)——抽象类与接口的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: VMWare mac os x 优化神器
- 下一篇: java编码什么时候需要增加空格_Jav