父类和子类同名的变量和方法决定于哪个
先看例子
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修饰是静态的方法,但是这个方法一般无法在外部调用