覆盖"静态"带有"非静态"的方法/字段方法/场

时间:2014-06-25 21:12:36

标签: java inheritance static static-methods

这里如果我尝试在子类中不使用static来覆盖静态方法,它会给我一个错误..虽然这不是静态变量的情况。为什么呢?

class A {
    static int a;
    static void a() {
       System.out.println("in A");
    }
}


class B extends A {
    int a=9;/*this does not give an error*/
    void a()/*this statement gives an error*/ {
       System.out.println("In B"+(A.a));
    }
}


class Test {

    public static void main(String []args) {   
        B b1=new B();
        b1.a();         
    }
}

4 个答案:

答案 0 :(得分:0)

字段不能过度使用。

它与Java命名范围有关。 Java可以解决字段名称的模糊性,而不是使用方法。

在B中,JVM不知道你是否想要调用A.a()或B.a()

答案 1 :(得分:0)

答案是: 应用于方法的静态意味着您可以在没有实例的情况下访问该方法,该类的对象应用于变量意味着您无法在代码中修改该变量。 在成瘾中,覆盖不关心您实际覆盖的方法中的变量。 这是因为override正在用新的方法替换该方法。 伪代码中的示例

 Class Triangle {
     public method calcArea() {
          // generic method
      }
 }

 Class RightTriangle extend Triangle {
      public method calcArea() {
           // area needs to be calculated in different way, so I specify a new Area method
      }
 }

 Class Main {
      public Main() {
           Triangle a;
           RigthTriangle b;
           a.calcArea(); // Calling Triangle.area!
           b.calcArea(); // calling RightTriangle.area!
      }
 }               

答案 2 :(得分:0)

这是因为出于某些奇怪的原因,实际上可以通过引用调用static方法。要调用的静态方法基于引用的类型而不是对象,这意味着允许具有与static方法相同签名的实例方法会产生关于什么的模糊性打电话的方法。

例如,如果允许这样做:

class A {
    static void method() {
        System.out.println("A");
    }
}

class B extends A {
    void method() {
        System.out.println("B");
    }
}

class Main {
    public static void main(String[] args) {
        A b = new B();
        b.method();
    }
}

会发生什么?是否应该调用A的实现,因为bA引用?或者应该调用B的实现,因为bB个对象?

因为两个选项同样有效,所以不允许实例方法“覆盖”static方法,确保所有方法调用都有效。


现在,对于字段(静态和非静态)都不是这样,因为字段不能在子类中重写,只能隐藏。因此,编译器可以根据引用的类型轻松找出所需的字段。

答案 3 :(得分:0)

静态方法不显示运行时多态性。因此,通过规则,静态方法在编译期间得到解决。通过声明一个静态方法,您将隐藏它。所以没有子类可以看到它。但这是可能的。

class A {
    static void test() {
        System.out.println("A");
    }
}

class B extends A {
    static void test() {
        System.out.println("B");
    }
}

这是因为B中的test()是B的方法,A中的test()是编译器理解的A方法。所以,如果你运行这个 class Test {

public static void main(String []args) {   
    B b1=new A();
    b1.test();         
}

在编译时看到b1编译器的引用类型知道你正在调用B的测试,即使在运行时该对象将是A的