摘自 http://m.tkk7.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();