Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a bad idea to declare a final static method?

I understand that in this code:

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

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

.. the static method in Bar 'hides' the static method declared in Foo, as opposed to overriding it in the polymorphism sense.

class Test {
    public static void main(String[] args) {
        Foo.method();
        Bar.method();
    }
}

...will output:

in Foo
in Bar

Re-defining method() as final in Foo will disable the ability for Bar to hide it, and re-running main() will output:

in Foo
in Foo

(Edit: Compilation fails when you mark the method as final, and only runs again when I remove Bar.method())

Is it considered bad practice to declare static methods as final, if it stops subclasses from intentionally or inadvertantly re-defining the method?

(this is a good explanation of what the behaviour of using final is..)

like image 750
brasskazoo Avatar asked Dec 19 '09 08:12

brasskazoo


3 Answers

I don't consider it's bad practice to mark a static method as final.

As you found out, final will prevent the method from being hidden by subclasses which is very good news imho.

I'm quite surprised by your statement:

Re-defining method() as final in Foo will disable the ability for Bar to hide it, and re-running main() will output:

in Foo
in Foo

No, marking the method as final in Foo will prevent Bar from compiling. At least in Eclipse I'm getting:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: Cannot override the final method from Foo

Also, I think people should always invoke static method qualifying them with the class name even within the class itself:

class Foo {   private static final void foo()   {     System.out.println("hollywood!");   }    public Foo()   {     foo();      // both compile     Foo.foo();  // but I prefer this one   } } 
like image 96
Gregory Pakosz Avatar answered Sep 16 '22 15:09

Gregory Pakosz


Static methods are one of Java's most confusing features. Best practices are there to fix this, and making all static methods final is one of these best practices!

The problem with static methods is that

  • they are not class methods, but global functions prefixed with a classname
  • it is strange that they are "inherited" to subclasses
  • it is surprising that they cannot be overridden but hidden
  • it is totally broken that they can be called with an instance as receiver

therefore you should

  • always call them with their class as receiver
  • always call them with the declaring class only as receiver
  • always make them (or the declaring class) final

and you should

  • never call them with an instance as receiver
  • never call them with a subclass of their declaring class as receiver
  • never redefine them in subclasses

 

NB: the second version of you program should fails a compilation error. I presume your IDE is hiding this fact from you!

like image 35
akuhn Avatar answered Sep 17 '22 15:09

akuhn


If I have a public static method, then it's often already located in a so-called utility class with only static methods. Self-explaining examples are StringUtil, SqlUtil, IOUtil, etcetera. Those utility classes are by itselves already declared final and supplied with a private constructor. E.g.

public final class SomeUtil {

    private SomeUtil() {
        // Hide c'tor.
    }

    public static SomeObject doSomething(SomeObject argument1) {
        // ...
    }

    public static SomeObject doSomethingElse(SomeObject argument1) {
        // ...
    }

}

This way you cannot override them.

If yours is not located in kind of an utility class, then I'd question the value of the public modifier. Shouldn't it be private? Else just move it out to some utility class. Do not clutter "normal" classes with public static methods. This way you also don't need to mark them final.

Another case is a kind of abstract factory class, which returns concrete implementations of self through a public static method. In such case it would perfectly make sense to mark the method final, you don't want the concrete implementations be able to override the method.

like image 37
BalusC Avatar answered Sep 18 '22 15:09

BalusC