【问题标题】:Regarding static method overriding关于静态方法覆盖
【发布时间】:2012-05-05 11:33:23
【问题描述】:

在覆盖静态方法的情况下..我在下面开发了这个代码

class Ab {  
    static void getF() {
        System.out.println("I am saral");
    }
}

class Ham extends Ab {
    static void getF() {
        System.out.println("I am saral saxena");
    }
    public static void main(String[] args) {
        // Ham h = new Ham();
        // h.getF(); //Ham
        Ab a = new Ham();
        a.getF(); // Ab class
    }
}

现在我的疑问是,如果在我使用多态行为时覆盖静态方法,Ab a = new Ham(); 在这个阶段我仍然得到类Ab 的方法getF();,请告知。

【问题讨论】:

    标签: java static-methods overriding


    【解决方案1】:

    不能覆盖静态方法。

    静态方法属于类。您可以致电 Ab.getF()Ham.getF() - 您在编码时选择了哪个。

    在类层次结构中将静态方法命名为相同没有任何影响(除了可能对程序员造成混淆)。静态方法是属于类而不是实例的浮动代码。只有实例方法对覆盖敏感。

    出于这个原因,在实例上调用静态方法(就像你一样)是一种糟糕的风格,因为它使该方法看起来是一个实例方法。它在语言中是允许的,但会导致程序员混淆,从而导致错误,特别是如果静态方法的名称类似于实例方法 - 例如,发现名为 setName(String) 的方法是静态方法可能是正当杀人的理由。

    【讨论】:

    • @Bohemian..是的,这个概念是静态方法被隐藏而不是被覆盖
    • 不 - 它们不是隐藏的(或称为 shadowed)。静态方法没有这样的概念。
    • 谢谢,能不能详细解释一下。
    • 您声明您的 a 属于 Ab 类。当你在 a 上调​​用静态方法时,它会调用类的静态方法,即 Ab。尝试将变量转换为:Ham other = (Ham)a;,然后调用other.getF();。顺便说一句,更好的变量命名不会伤害例如解释;)
    【解决方案2】:

    在编译时,实例调用的静态方法被编译为使用声明变量的类调用,而不是实际实例化的类,因此a.getF(); 将导致Ab.getF(); 而不是Ham.getF(); .

    一般来说,使用实例而不是类名调用静态方法是一种非常糟糕的做法。 (我认为最好的例子是在thread 实例上调用Thread.sleep(),假设它会导致实例线程休眠,但实际上当前线程会)

    【讨论】:

      【解决方案3】:

      重写静态函数是不可能且无用的(我避免使用术语方法,因为方法与对象相关)。

      当需要根据对象的类调用不同的静态函数时,这样做

      class Ab {  
       private static void getF() {
          System.out.println("I am saral");
       }
       public void doit () {
         getF ();
       }
      }
      class Ham extends Ab {
       private static void getF() {
          System.out.println("I am saral saxena");
       }
       @Override
       public void doit ()
       {
          getF ();
       }
       public static void main(String[] args) {
          Ab a = new Ham();
          a.doit(); // Ham class
      }
      

      }

      顺便说一句,使用 get 作为函数返回 void 很奇怪

      【讨论】:

        【解决方案4】:

        第一件事是不能将派生类中具有名称和签名的静态方法与基类中的情况相同的情况称为覆盖。

        这是因为在重写的情况下,编译器不会为函数调用生成字节码,因为实际调用的方法将在运行时解析,具体取决于 引用变量的多态行为。

        重写实际上是由编译器的这种动态行为定义的(而不是由具有相同签名方法的基类和子类定义,这些只是重写的先决条件)。

        静态方法是类实体,因此绑定到引用变量而不是运行时对象,因此方法调用仅在编译时解析(基于引用变量的类型或类名,如果由它引用。

        类似地,如果您在父类和子类中都有同名和类型的公共实例变量或静态变量,则将选择具有变量类型的变量而不是运行时对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-06-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-04
          • 2010-10-27
          相关资源
          最近更新 更多