摘自 http://www.aygfsteel.com/crazycy/archive/2008/10/19/74622.html#235256

< 示例1>


 1 class  Base {
 2      int  x  =   2 ;
 3      int  method() {
 4          return  x;
 5     }

 6 }

 7
 8 class  SubClass  extends  Base {
 9      int  x  =   3 ;
10      int  method() {
11          return  x;
12     }

13 }

14
15 public   class  Main 
16          public   static   void  main(String[] args)  {
17         Base b  =   new  SubClass ();
18         System.out.println(b.x);
19         System.out.println(b.method());
20     }

21 }

2 , 3

 

<練習>


 1 class   s1    {   
 2        public   String  s = " s1 " ;   
 3        public   String  get()   {   
 4            return   s;   
 5       }
   
 6 }
   
 7 class   s2   extends   s1    {   
 8       public    String   s = " s2 " ;   
 9        public    String   get()    {   
10            return    s;   
11       }
   
12  }
   
13 public     class    s   {   
14        public     static     void    main(String[]   args)   {   
15           s1  a    =     new   s2();   
16           System.out.println(a.s);   
17           System.out.println(a.get());     
18       }
   
19  }
  

   這個地方就是多態的一個陷阱;   

 多態是對方法而言的,不是對變量;   

  s1 a  =   new  s2();這里生成的對象是s1類的實例,但是是由s2類構造的;   
  java中對變量的選擇是靜態的,對方法的選擇是動態的,是在運行時決定的。(static除外)   
   運行時實際上調用的是實例的方法,即s1的方法;但對于繼承(多態的一種方式),方法的定位是在動態執行時選擇的,選擇實際構造者,因此就出現了本題的現象了。   
另外:多態是對方法而言的,不是對變量;這樣說有些不嚴密,方法應該有個修飾,就是除了final修飾的方法外,java中對函數的調用都是后期綁定,所謂的后期綁定就是動態選擇
 摘自 崔毅解答csdn疑問時給出的分析

注意以下的方法都被修飾了final

示例2>以下哪里會出錯?


 1 class  Base {
 2      private   final   void  f() {
 3         System.out.println( " Base.f() " );
 4     }

 5 }

 6
 7 class  Derived  extends  Base {
 8      public   final   void  f() {
 9         System.out.println( " Derived.f() " );
10     }

11 }

12
13 public   class  Main 
14          public   static   void  main(String[] args)  {
15         Derived op1  =   new  Derived();
16         Base op2 = op1;
17         op1.f();
18         op2.f();
19     }

20 }

21

op2.f(); 處出錯!
<示例3>


 1 class    Parent {   
 2        private     void    method1() {   
 3           System.out.println( " Parent's   method1() " );   
 4       }
   
 5        public     void    method2() {   
 6           System.out.println( " Parent's   method2() " );   
 7           method1();   
 8       }
   
 9   }
   
10    class    Child    extends    Parent {   
11        public     void    method1() {   
12          System.out.println( " Child's   method1() " );   
13       }
   
14        public     static     void    main(String   args[]) {   
15           Parent   p    =     new    Child();   
16           p.method2();   
17       }
   
18   }
   

1 答案是:prints:   parent’s   method2()     parent’s   method1()   
2 如果把父類中method1改成public,那么答案是
3 prints:   parent’s   method2()     child’s   method1()


分析

多態:

Java 中的函數,除了聲明外 final 的外,都是后期綁定。

所謂綁定是建立“函數調用”和“函數本體”的關聯。、

所謂的后期綁定是指執行時根據對象類別而進行

多態僅僅對函數而言,不對變量而言;

變量的訪問依賴于編譯期引用指向的類型;

方法的訪問依賴于執行期對象的類型;

向上轉型后,調用某個函數,若 derived class overriding 了該函數,則會調用該 derived class 中的函數,否則會調用 base class 中的函數。

向上轉型后,只能調用 base class 中被 derived class overriding 的函數,不能調用 derived class extend 函數。

向上轉型后,只能調用 base class 中的方法,不能調用 derived class 中的擴展方法 


 1 public   class  CalC  {
 2      void  amethod() {
 3         System.out.println( " CalC.amethod " );
 4     }

 5     CalC() {
 6         amethod();
 7         System.out.println( " Hu? " );
 8     }

 9      public   static   void  main(String[] args)  {
10         CalC cc  =   new  CalChild();
11         cc.amethod();
12     }

13 }

14 class  CalChild  extends  CalC {
15      void  amethod() {
16         System.out.println( " CalChild.amethod " );
17     }

18 }

1 output:
2 CalChild.amethod
3 Hu ?
4 CalChild.amethod
5 為什么CalC Constructor調用的不是自己的amethod()呢

1 方法在內存中只有一個備份,所以的對象都共享這個備份,為了區分開到底是哪個對象在調用這個方法,關鍵的地方就是this的使用。this把調用方法的上下文對應到當前對象上。
2
3 第二,調用java中的所有成員變量或者成員函數都隱含了this。
4
5 所以這個地方就很明了了:構造子類,this指針代表的當前對象是子類實例,子類實例為啥不調用自己overriding的方法呢?!
6


--------取于 崔毅 之《java編程指南》《java編程思想》學習筆記l
以下是強化和復習:

1 多態只針對非final方法;
 不針對變量、final方法

2方法[非final]是運行時對應對象
 變量、fianl是編譯期間對應對象

3多態只能調用父類中有的方法(向上擴展后)
 不能調用父類中沒有的方法;
 不能調用子類中擴展父類[not overridding]方法
 
4多態定義:指的是使用同一個實現接口,以實現不同的對象實例
 多態好處:多態讓程序依賴接口或者抽象類,而不是具體類
p.s
 1class  Base {
 2     int  x  =   2 ;
 3     String s="s1";
 4     int  method() {
 5       return  x;
 6     }

 7     public String method2(){
 8         return s;
 9   }
 
10 }

11 class  SubClass  extends  Base {
12    int  x  =   3 ;
13    String s="s2";
14    int  method() {
15      return  x;
16    }

17    public String method2(){
18        return s;
19  }
 
20}
 
21public class t4 {
22
23    public static void main(String[] args) {
24         Base b  =   new  SubClass ();
25         System.out.println(b.x);
26         System.out.println(b.method());
27         System.out.println("-----用new SubClass會如何?------");
28         System.out.println(new SubClass().x); //相當于 SubClass a=new SubClass(); 然后a.x
29         System.out.println(new SubClass().method());//相當于a.method();
30         System.out.println(new SubClass().s);
31         System.out.println(new SubClass().method2());
32         System.out.println("-----直接new SubClass的test結束------");
33         System.out.println(b.s);
34         System.out.println(b.method2());
35         
36
37    }

38
39}

40
 12
 23
 3-----用new SubClass會如何?------
 43
 53
 6s2
 7s2
 8-----直接new SubClass的test結束------
 9s1
10s2
11
這說明直接寫new son();//相當于 son son=new son();