`
mzhj
  • 浏览: 227469 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Can I override a static method?

阅读更多
Can I override a static method?

Many people have heard that you can't override a static method. This is true - you can't. However it is possible to write code like this:
class  Foo  {
    public  static  void  method() {
        System .out.println("in Foo" );
    }
}

class  Bar  extends  Foo  {
    public  static  void  method() {
        System .out.println("in Bar" );
    }
}
This compiles and runs just fine. Isn't it an example of a static method overriding another static method? The answer is no - it's an example of a static method hiding another static method. If you try to override a static method, the compiler doesn't actually stop you - it just doesn't do what you think it does.

So what's the difference?

Briefly, when you override a method, you still get the benefits of run-time polymorphism, and when you hide , you don't. So what does that mean? Take a look at this code:
class  Foo  {
    public  static  void  classMethod() {
        System .out.println("classMethod() in Foo" );
    }

    public  void  instanceMethod() {
        System .out.println("instanceMethod() in Foo" );
    }
}

class  Bar  extends  Foo  {
    public  static  void  classMethod() {
        System .out.println("classMethod() in Bar" );
    }

    public  void  instanceMethod() {
        System .out.println("instanceMethod() in Bar" );
    }
}
 
class  Test  {
    public  static  void  main(String [] args) {
        Foo  f = new  Bar ();
        f.instanceMethod();
        f.classMethod();
    }
}
If you run this, the output is

instanceMethod() in Bar

classMethod() in Foo
Why do we get instanceMethod from Bar, but classMethod() from Foo? Aren't we using the same instance f to access both of these? Yes we are - but since one is overriding and the other is hiding, we see different behavior.

Since instanceMethod() is (drum roll please...) an instance method, in which Bar overrides the method from Foo, at run time the JVM uses the actual class of the instance f to determine which method to run. Although f was declared as a Foo, the actual instance we created was a new Bar(). So at runtime, the JVM finds that f is a Bar instance, and so it calls instanceMethod() in Bar rather than the one in Foo. That's how Java normally works for instance methods.

With classMethod() though. since (ahem ) it's a class method, the compiler and JVM don't expect to need an actual instance to invoke the method. And even if you provide one (which we did: the instance referred to by f) the JVM will never look at it. The compiler will only look at the declared type of the reference, and use that declared type to determine, at compile time , which method to call. Since f is declared as type Foo, the compiler looks at f.classMethod() and decides it means Foo.classMethod. It doesn't matter that the instance reffered to by f is actually a Bar - for static methods, the compiler only uses the declared type of the reference. That's what we mean when we say a static method does not have run-time polymorphism.

Because instance methods and class methods have this important difference in behavior, we use different terms - "overriding" for instance methods and "hiding" for class methods - to distinguish between the two cases. And when we say you can't override a static method, what that means is that even if you write code that looks like it's overriding a static method (like the first Foo and Bar at the top of this page) - it won't behave like an overridden method.

So what about accessing a static method using an instance?

It's possible in Java to write something like:

   f.classMethod();

where f is an instance of some class, and classMethod() is a class method (i.e. a static method) of that class. This is legal, but it's a bad idea because it creates confusion. The actual instance f is not really important here. Only the declared type of f matters. That is, what class is f declared to be? Since classMethod() is static, the class of f (as determined by the compiler at compile time) is all we need.

Rather than writing:

    f.classMethod();
It would be better coding style to write either:
    Foo.classMethod();
or
    Bar.classMethod(); 
That way, it is crystal clear which class method you would like to call. It is also clear that the method you are calling is indeed a class method. o;'oi;'i Barring that, you could always come up with this monstrosity:
    f.getClass().getMethod("classMethod", new Class[]).invoke(null, new Object[]);

But all this could be avoided by simply not trying to override your static (class) methods. :-)

Why does the compiler sometimes talk about overriding static methods?

Sometimes you will see error messages from the compiler that talk about overriding static methods. Apparently, whoever writes these particular messages has not read the Java Language Specification and does not know the difference between overriding and hiding. So they use incorrect and misleading terminology. Just ignore it. The Java Language Specification is very clear about the difference between overriding and hiding, even if the compiler messages are not. Just pretend that the compiler said "hide" rather than "override"..

分享到:
评论

相关推荐

    Google C++ Style Guide(Google C++编程规范)高清PDF

    How can we use a class Foo in a header file without access to its definition? We can declare data members of type Foo* or Foo&. We can declare (but not define) functions with arguments, and/or ...

    Java - A Beginner’s Guide - Sixth Edition - Herbert Schildt

    It covers method overloading, static methods, and constructors. It also explores class relationships such as inheritance and composition. These concepts are crucial for creating reusable code and ...

    java面试宝典

    196、Can a database connection pool be instantiated in init method of servlet instead of server connection pool? What will be the problem? 46 综合部分 46 197、Class.forName的作用?为什么要用? 47 198、...

    第三章 继承与多态 掌握封装的含义及用法 什么是继承? 继承有什么作用? 怎么写继承?

    System.out.println("Car can run faster than a vehicle."); } } ``` **方法的重载(Overloading)** 是指在一个类中可以定义多个同名的方法,但这些方法的参数列表必须不同。这里的不同可以是参数的类型、数量...

    cJSON-master.zip

    You can change the build process with a list of different options that you can pass to CMake. Turn them on with `On` and off with `Off`: * `-DENABLE_CJSON_TEST=On`: Enable building the tests. (on ...

    ViewPager 放大缩小左右移动

    * This method will be invoked when a new page becomes selected. * Animation is not necessarily complete. * * @param position * Position index of the new selected page. */ public ...

    BCGControlBarPro.v12.00

    Override a new 'OnCalculatorUserCommand' method to implement your calculator commands. Please take a look at BCGPControls example and RibbonGadgets/SkinnedDialog samples to see these new features ...

    acpi控制笔记本风扇转速

    longer released before a blocking operation during control method execution. This effectively makes the AML Interpreter single- threaded. The overhead of a semaphore per-method is eliminated. Fixed a...

    Effective C#

    - **Purpose:** Ensuring that the default state of a value type is valid can prevent errors. - **Example:** Define a `PersonId` struct that uses 0 as the default value. **Item 20: Prefer Immutable ...

    各大公司企业真实面试题-阳光海融科技面试题请用Java语言编写完成如下任务的程序代码.doc

    for (int i : a) { System.out.print(i + " "); } } private static void reverse(int[] arr) { int start = 0; int end = arr.length - 1; while (start ) { int temp = arr[start]; arr[start] = arr...

    Java编写的简易计算器

    public static void main(String[] args) { new Calculator().creatGUI(); } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String act = e....

    BURNINTEST--硬件检测工具

    can stop in the operating system - i.e. there is a problem in the operating system/ device driver that prevents control being returned to the BurnInTest for that test. This was added for ...

    基于extjs的.NET3.5控件Coolite 1.0.0.34580(Preview预览版)

    59. Removed the static Instance method from Ext.Net.MessageBox class. The MessageBox class was changed from an Singleton to just a standard (non-singleton) class. Using the X.Msg Helper is ...

    java学习笔记

    System.out.println("Animal makes a sound"); } } public class Cat extends Animal { @Override public void makeSound() { System.out.println("Meow"); } } ``` - **注意**: - `final`和`private`...

    cglib动态代理

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if (!"maurice".equals(this.name)) { System.out.println("AuthProxy: you have no permits to do ...

    tomcat-8_API

    referenced by a shared static field in the web application classloader, and putting them in the shared classloader instead (JARs should be put in the "lib" folder, and classes should be put in the ...

Global site tag (gtag.js) - Google Analytics