1、JAVA支持的多態性質主要是爲兩種:靜態多分派和動態單分派。
- 靜態多分派在JAVA中的表現形式即:重載。主要由靜態方法和私有方法構成(還有實例構造方法、父類方法)。他們的引用在類加載之初就已經被確定了。一個是類級別的,一個是私有方法,private訪問限定了它不能被子類訪問並覆寫。
- 動態單分派的表現形式爲:覆寫(Override)
public class Client {
public static void main(String[] args) {
Base base = new Sub();
//調用非靜態方法
base.doAnything();
//調用靜態方法
base.doSomething();
}
}
class Base{
//父類靜態方法
public static void doSomething(){
System.out.println("我是父類靜態方法");
}
//父類非靜態方法
public void doAnything(){
System.out.println("我是父類非靜態方法");
}
}
class Sub extends Base{
//子類同名、同參數的靜態方法
public static void doSomething(){
System.out.println("我是子類靜態方法");
}
//覆寫父類的非靜態方法
@Override
public void doAnything(){
System.out.println("我是子類非靜態方法");
}
}點擊打開鏈接
@來自http://www.cnblogs.com/DreamDrive/p/5428678.html注意這裏的Base base=new Sub();這一行代碼,很明顯這是典型的使用派生類,使用了父類的引用指向子類的對象,向上轉型。其中,base的靜態類型是Base,這個在編譯期就已經確定,而實際類型Sub是在運行期才能確定的。
舉個例子,Sub繼承了父類Test,父類中有兩個重載方法,一個參數類型是Test,一個是Sub。這時候我們調用這個重載方法,將Test test=new Sub();傳入進去。前面我們提到了,靜態分派的典型應用是重載,而這個例子中test的靜態類型是Test,那麼答案應該是多少呢?
沒錯,就是調用了Test類型的重載方法。因爲重載是靜態分派,所以它的類型在編譯期就已經確定了,在確定使用哪一個重載方法的時候,是根據變量的靜態類型來確定的。
動態分派:
前面提到了JAVA的動態分派是動態單分派,即在執行覆寫的時候,只有一個宗量——參數。即參數是那個類型的,就覆寫了哪一個方法。
還是剛纔那個例子,只不過稍微改動了一下子類,添加了兩個方法, 和Test中一樣,一個靜態方法和一個實例方法。當傳入的類型是Sub時,調用了子類Sub中的test方法。
public class Test{
public static String test(Test test){
return "It's Test";
}
public String test(Sub sub){
return "It's Sub";
}
public static void main(String[]args) {
Test test=new Sub();
Test test2=new Test();
Sub sub=new Sub();
System.out.println(test.test(sub));
}
}
class Sub extends Test{
public static String test(Test test){
return "It's Sub Test";
}
public String test(Sub sub){
return "It's Sub Sub ";
}
}
輸出:It's Sub Sub靜態方法:
那麼如果傳入Test類型的參數呢?
System.out.println(test.test(test));
我們改動一下,將main方法中最後一句的參數改成test2,看看結果: It's test
這次卻沒有覆寫父類的方法,調用的不再是子類中的test方法,而是父類中的方法,這是爲什麼呢?
這是因爲就像我們前面提到的,靜態方法和私有方法不能被覆寫,他們在編譯期就已經確定了類型,這時候又回到了最開始提到的靜態分派的過程中。
私有方法:
和靜態方法一樣,都不執行覆寫
類的成員變量:
在Test類和Sub類中, 分別加入public int i=1,=2;輸出test.i,結果1。
因爲類的成員變量也是一般的靜態分派。
基本數據類型==和包裝類型的equals()方法:
long a=12;
float f=12.0f;
System.out.println(a==f);//輸出true 因爲f會先轉換成long類型 再進行數值的比較
而如果將其中一個改成包裝類型,在進行equals()方法比較,則會輸出falsepublic boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
那如果改成Number類呢,我們知道Byte,Double,
Float,
Integer, Long,
Short都是Number類的直接子類。Long a=new Long(12);
Number b=12;
System.out.println(b.equals(a));//輸出false
結果還是false,因爲Number類的equals()方法是直接判定是否==