父类和子类同名的变量和方法决定于哪个

先看例子

 1 /*
 2  * "重写"只能适用于实例方法.不能用于静态方法.
 3  * 对于静态方法,只能隐藏(形式上被重写了,但是不符合的多态的特性)
 4  * “重写”是用来实现多态性的,只有实例方法是可以实现多态,而静态方法无法实现多态。例如:
 5 
 6         Employee man = new Manager();
 7 
 8         man.test();
 9 
10    实例化的这个对象中,声明的man变量是Employee类的,变量名存在栈中,
11    而内存堆中为对象申请的空间却是按照Manager类来的,
12    就是Employee类型的man变量的指针指向了一个Manager类的对象。
13    如果对这个man调用方法,调用的是谁的?
14    如果是非静态方法,编译时编译器以为是要调用Employee类的,
15    可是实际运行时,解释器就从堆上开工了,实际上是从Manager类的那个对象上走的,
16    所以调用的方法实际上是Manager类的方法。有这种结果关键在于man实际上指向了Manager类对象。
17    现在用man来调用静态方法,实际上此时是Employee类在调用静态方法,
18  Employee类本身肯定不会指向Manager类的对象,那么最终调用的是Employee类的方法。
19   */
20 class Father{
21     static int age = 7;
22     int num = 0;
23     static void print(){
24          System.out.println ("father print"+age);
25      }
26     
27     public void paint(){
28         System.out.println ("father paint"+num+age);
29     }
30 }
31 class Child1 extends Father{
32     static int age = 8;
33     int num = 1;
34     static void print(){
35          System.out.println ("child1 print"+age);
36      }
37     public  void paint(){
38         System.out.println ("child1 paint"+num+age);
39     }
40 }
41 
42 class Child2 extends Father{
43     static int age = 9;
44     int num = 2;
45       public  void paint(){
46          System.out.println ("child2 paint"+num+age);
47      }
48 }
49 
50 class test{
51     public static void main (String[] args) {
52         System.out.println("此处暂且将对静态方法的再次编写叫做覆盖,将对普通方法的再次编写叫做重写");
53         System.out.println("其实在大多数情况下我们所说的重写和覆盖式一个意思,但是有些书上会把覆盖和重写区别对待");        
54          Father ff   = new Father();
55          ff.print();//father print7                           //覆盖,覆盖的方法决定于引用类型,即静态绑定 
56          ff.paint();//father paint07                          //重写,重写方法决定于对象类型
57          
58          Father fc1  = new Child1();           
59          fc1.print();//father print7                          //覆盖,覆盖的方法决定于引用类型,即静态绑定 
60          fc1.paint();//child1 paint18                          //重写,重写方法决定于对象类型
61          
62          Child1 c1c1 = new Child1();
63          c1c1.print();//child1 print8                         //覆盖,覆盖的方法决定于引用类型,即静态绑定 
64 
65          Father fc2  = new Child2();           
66          fc2.paint();//child2 paint29                          //重写,重写方法决定于对象类型
67          
68          Child2 c2c2 = new Child2();
69          c2c2.paint();//child2 paint29                         //重写,重写方法决定于对象类型
70      }
71 }
72 
73 /*
74  * 总结:
75  * 变量为哪个决定于对象类型(静态方法不能调用普通变量)
76  * 普通方法决定于对象类型
77  * 静态方法决定于引用类型
78  * 
79  * ---------也就是说除了静态方法为那个决定于引用类型外,其他的都决定于对象类型---------
80  * */

 "重写"只能适用于实例方法.不能用于静态方法.
 对于静态方法,只能隐藏(形式上被重写了,但是不符合的多态的特性)
 “重写”是用来实现多态性的,只有实例方法是可以实现多态,而静态方法无法实现多态。例如:

        Employee man = new Manager();

        man.test();

 实例化的这个对象中,声明的man变量是Employee类的,变量名存在栈中,
 而内存堆中为对象申请的空间却是按照Manager类来的,
 就是Employee类型的man变量的指针指向了一个Manager类的对象。
 如果对这个man调用方法,调用的是谁的?
 如果是非静态方法,编译时编译器以为是要调用Employee类的,
 可是实际运行时,解释器就从堆上开工了,实际上是从Manager类的那个对象上走的,
 所以调用的方法实际上是Manager类的方法。有这种结果关键在于man实际上指向了Manager类对象。
 现在用man来调用静态方法,实际上此时是Employee类在调用静态方法,
 Employee类本身肯定不会指向Manager类的对象,那么最终调用的是Employee类的方法。


 * 总结:
 * 变量为哪个决定于对象类型(静态方法不能调用普通变量)
 * 普通方法决定于对象类型
 * 静态方法决定于引用类型
 *
 * ---------也就是说除了静态方法为那个决定于引用类型外,其他的都决定于对象类型---------

静态绑定就是所谓的程序编译时绑定,java中的变量都是静态绑定的,方法只有static和final(所有private默认是final的,子类不可能修改父类的私有方法)是静态绑定的。编译时已经确切知道程序所要执行的是哪一个类的哪一个方法,不存在重载等问题。
例如:static、private修饰的方法或者变量,对于方法的调用或者变量的使用是不存在歧义的,所以在编译时即可确定。

但是要注意这里虽然说private修饰是静态的方法,但是这个方法一般无法在外部调用

posted @ 2012-08-16 22:16  大头鬼  阅读(446)  评论(0编辑  收藏  举报