摘自 http://www.blogjava.net/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();