2016-08-04 74 views
1

代码:为什么可以重写方法但变量不能?

public class ClassTest { 

     public static void main(String args[]) { 
      test1 cc = new test2(); 
      System.out.println(cc.A); 
      System.out.println(cc.B); 
      cc.method1(); 
      cc.method2(); 
     } 

} 

class test1 { 
     static int A = 2; 
     int B = 5; 

     void method1() { 
      System.out.println("Inside method 1 test1"); 
     } 

     static void method2() { 
      System.out.println("Inside method2 test1"); 
     } 
} 

class test2 extends test1 { 
     static int A = 4; 
     int B = 6; 

     void method1() { 
      System.out.println("Inside method 1 test2"); 
     } 

     static void method2() { 
      System.out.println("Inside method 2 test2"); 
     } 
} 

OUTPUT:

内部方法1 TEST2

里面方法2 TEST1

问:

为什么只有方法覆盖,但变量保持不变?

此行为是否有名称? (如方法的“覆盖”)

+0

问题“为什么”很棘手 - 这是因为语言的设计者决定像这样做,原因是简单,高效,清晰,等等。 – RealSkeptic

+0

这就是语言的设计。至于为什么,你不得不问Java的发明者。 –

+0

你正在调用一个实例的静态方法? ''static void method2()' - >'cc.method2();' – Fildor

回答

1

这里发生了什么事,你已经使用type1引用指向的test2一个实例。你可以这样做,因为test2是一种test1 - 这叫做多态性

test2test1衍生,因此当你创建类型的对象test2你将基本上已经创建两个对象,test2test1(不会驻留在堆作为自主对象)。

JVM将从其引用访问对象的字段(因为Java是静态类型语言)。

所以,尽管test2隐藏test1,这两个领域在试图从test1参考Java访问他们自动进入test1

这是关于它的领域。

当处理方法时,我们有一个更复杂的问题。方法是改写,因此,当方法表建立时,方法test2覆盖test1的方法。但是,静态方法不是实例方法。

因此,当试图访问来自test1参考的test2的静态方法method2时,您“滥用”了代码。你应该打电话给test1.method2()或者,如果你想访问静态方法test2你应该使用test2.method2()

希望我解释的不够好......

2

覆盖方法意味着让相同的方法调用执行另一个方法体(在子类中)。

对于变量“覆盖”是不必要的:你可以用覆盖这个变量的值。

在同名子类中声明变量隐藏父类变量并引入了一个附加字段。

对于方法是可重写的,需要一种特殊的机制,使得在码的地方可能会调用实际的类对象的指定方法。这与访问字段相反。

1

在上述例子中,你正在创建基类时将采取的基准值A = 2,B = 5,它将分配内存also.so当倍率到派生类,基础类变量隐藏派生类的变量值这就是为什么它无法在派生类中重写的原因。

0

在行:System.out.println(cc.A);
这不是调用静态成员的正确方法,你应该总是使用类的名称,例如:System.out.println(test1.A);

按Java规范中,实例变量在扩展时不会被子类从超类中覆盖。
变量是静态的还是非静态的。只有方法可以被重写。 这就是为什么cc.A & cc.B输出是从test1

对于方法覆盖:
代码cc.method1();这里overrriding发生,对象类型(类即实例)实际上确定哪些方法是在选定的运行时,通过此对象声明new test2()在此代码中:test1 cc = new test2();
编译器首先检查test1类中的方法,然后检查text2类中的方法,如果所有签名(参数,返回类型等)都相同它调用子类方法 ,因为它重写基类方法,因为实际对象是类test2

对于静态方法: 静态方法不能被重写,因为方法覆盖仅发生在动态的上下文中的方法(即,运行时)的查找。
静态方法(通过它们的名字)被静态地查找(即在编译时)。
这就是为什么输出是从类test1

对于Java中的“静态方法”,确切的调用方法是在编译时确定的。
您明确指定要执行静态方法的类的名称

相关问题