在學習Java的過程中,多態與類是最多與最常見的形式了,最近剛剛接觸內部類不久,發現內部類的確很深奧,而且還有點難理解。
由於水平有限,本文有待修改!
多態:分爲靜態多態和動態多態。而多態的主要意思就是多種形態。
多態性:發送消息給某個對象,讓對象自行決定響應何種行爲;
通過將子類對象引用賦值給超類對象引用變量來實現動態方法調用
不能把父類對象引用賦給子類對象引用變量
一個類型引用只能引用引用類型自身含有的方法和變量
父類引用子類對象的時候,最後執行的是子類的方法
多態:判斷一個對象屬於哪個類的實例用instanceof操作符來判斷,
instanceof的語法: 引用對象名 instanceof操作符 類名
instanceof主要用在繼承關係中;
instanceof的返回類型是布爾類型;
instanceof的作用是判斷對象的類型;
多態的範圍包括:如果一個在對象裏,有繼承關係,那麼對象即屬於屬於父類類型又屬於子類類型,
如果沒有繼承關係,那麼對象只屬於所在類的類型;
靜態多態:方法的重載。代碼中可以直接識別的多條(編譯時多態);
靜態方法只能調用靜態方法和屬性,因爲非靜態的屬性和方法依賴於對象的存在纔可以使用,但是static類型的屬性和方法是不依賴對象的存在的;
靜態方法中不可以使用this和super關鍵字;因爲他們依賴於父類和自身的對象的存在,而static是不需要對象的存在的;如果使用了會發生語法錯誤。
在重寫時既不可以用靜態的方法重寫非晶態的方法,也不可以使用非靜態的方法重寫靜態的方法;
靜態屬性優先於對象屬性賦值;父類靜態屬性優先於子類靜態屬性賦值;
隱藏時不受static約束
靜態屬性被自己類創建的所有對象共享;
Static只可以修飾內部類;
動態多態:方法的重寫。動態多態調用對象。(運行時多態)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Abstract;被abstract修飾的類不可以實例化;如果要引用抽象化類需要聲明父類對象 指向子類對象的方式通過派生的
方法實現父類抽象方法的功能;
抽象類可以實現多重繼承,如果父類中的抽象方法不止一個,那麼子類就要繼承父類的多個抽象方法;但是可以不重寫父類的方法;
抽象類中可以沒有抽象方法,但是含有抽象方法的類必須被聲明爲抽象類;
抽象方法沒有方法體,需要通過派生的方法來實現抽象方法;
抽象類中的屬性可以被子類所繼承,但是子類的屬性不可以父類的方法所引用;
抽象類中的子類在重寫父類方法時局部變量不可以被public和static所修飾,只可以被final修飾;
子類在繼承父類時,如果父類時抽象類那麼子類也要聲明爲抽象類;所以接口中的方法越少,實現類越多越好,這樣可以體現模塊化的設計思想。對於接口的設計,應該在事件的中心思想去思考,創建一個最終的抽象方法來實現整個事件的核心主題。並且通過N個實現類來體現最終抽象方法。
在抽象類中子類在繼承父類的方法時,子類的返回類型必須和父類的返回類型一致;
接口的聲明: interface interfacename
使用interface創建接口,接口中只可以創建抽象對象。
實現類的語法:Class Classname implemets interface interfacename{實現接口的抽象方法}
在接口中創建的對象需要用實現類來完成接口中的抽象方法,並且接口中的抽象方法越多,那麼實現類重寫接口中的方法就越多,沒有實現Java思想的模塊化設計,所以在接口中的
接口:接口是特殊的抽象類,只允許書寫public static final修飾的屬性和public abstract 修飾的抽象方法
接口是抽象類,必須通過子類(實現類)重寫(實現)抽象方法,來完成具體操作
接口的作用:統一實現類共有的方法,從而使程序在不知道具體對象的情況下可以完成編寫。
接口可以繼承,並且一個子類可以有多個父類
一個類只能繼承一個直接父類,但是一個累類可以實現多個接口;(如果實現多繼承,那麼Java虛擬機會採用不同的綁定規則,就會增加程序的複雜度,而接口中只有抽象方法沒有實例變量和靜態方法所以一個類即使有多個接口也不會增加Java虛擬機進行動態綁定的複雜度因爲Java虛擬機永遠不會吧方法與接口綁定,只會把方法與他的實現類綁定)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
內部類:分爲靜態內部類,匿名內部類,同名內部類,局部內部類。
內部類可以直接訪問外部成員。
實例內部類:可以引用外部類的私有,公共,默認,靜態,受保護的,最終的屬性,並且可以重新外部類的方法。
局部內部類:
B類是A類的局部內部類,C類是B類的成員內部類;
局部內部類是定義在成員方法中的內部類;
局部內部類和實例內部類一樣不能包含靜態成員,
局部內部類和實例一樣可以訪問外部的所有成員,並且局部內部類還可以訪問所在方法中的final類型的參數和變量
public class A {
public void method(){
class B{
int v1;
int v2;
class C{
int v3;
}
}
B b=new B();
B.C c=b.new C();
}
}
局部內部類是在一個方法中定義的類,它的可見範圍是當前方法。
靜態內部類:靜態內部類只可以引用外部類的靜態屬性,並且不可以重新外部類的構造方法。因爲靜態方法只可以使用靜態屬性;並且靜態方法不需要再創建實例對象;
匿名類:匿名類沒有名字,匿名類本身沒有構造方法;
實例初始化代碼具有和構造方法同樣的效果,不過,前者不允許被重載,匿名類的實例只能有一種初始化方式
除了可以在外部類的方法內定義匿名類以外,還可以在聲明一個成員變量時,定義匿名類,
局部內部類的的名字在方法外是不可見的,因此與匿名類一樣,能夠起到封裝類型名字的作用。
匿名類的程序代碼比較簡短。
一個局部內部類可以有多個重載構造方法,並且客戶可以多次創建局部內部類的實例,而匿名類沒有重載構造方法,並且只能創建一次實例。
因此,如果只需要創建內部類的一個實例,那麼可以用匿名類,它使程序代碼比較簡短,如果需要多次創建內部類實例,那麼用局部內部類。
匿名類除了可以繼承類外,還可以實現接口。
package InnerClass1;
public abstract class A {
// A(int v){System.out.println("another constructor");}
// A(){System.out.println("default constructor");}
// void method(){System.out.println("from A");}//定義一個繼承A類的匿名類
A a=new A(){ //聲明變量時定義匿名類
void method(){System.out.println("inner");}
};
abstract void method();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package InnerClass1;
public class InnerClassMain {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// new A().method();
// A a=new A(){ //通過創建實例來創建匿名類,並且在外部類創建匿名類。
// void method(){System.out.println("from anonymous");}
// };
// a.method(); //打印from anonymous
//以下被註釋的局部內部類就等價於上面的實例引用
// class subA extends A{ //定義局部類
// void method(){System.out.println("from anonymous");}
// }
// A a=new subA(); //創建局部類實例
// final int v=1; //此處必須被定義爲final類型的屬性,否則編譯錯誤。
// A a=new A(v){ // 匿名類
// void method(){System.out.println("from anonymous"+v);}}; //使用局部變量V
// a.method();
//匿名類雖然沒有構造方法,但是可以在匿名類中提供一段實例初始化代碼,java虛擬機會在調用了父類的構造方法後,執行這段代碼!
// final int v=1;
// A a=new A(v){
// {System.out.println("initialize instance");}
// void method(){System.out.println("from anonymous");}
// };
// a.method();
// Thread t=new Thread(new Runnable(){ //此匿名類實現了Java.lang.Runnable接口,把這個匿名類的實例引用作爲參數,
// public void run(){ //傳給java.lang.thread類的構造方法,
// for(int i=0;i<100;i++)
// System.out.println(i);
// }
// });
// t.start();
//Thread t=new Thread(new Runnable(){此句代碼就等價於如下代碼
Runnable r=new Runnable(){
public void run(){
for(int i=0;i<100;i++)
System.out.println(i);
}
};
Thread t=new Thread(r);
t.run();
}
}