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