In java static methods are not inherited (or the right word is overridden) but they can be hidden.
The big different here is that they are not subjected to polymorphism as object method are.
public class C1 {
static public void M1() {
System.out.println("C1.M1().");
}
static public void main(String ... Args) {
M1();
}
}
public class C2 extends C1 {
static public void M1() {
System.out.println("C2.M1().");
}
static public void main(String ... Args) {
M1();
C1.main(Args);
}
}
When run C2.main(null)
, you will get:
C2.M1().
C1.M1().
As you can see,
calling M1()
in C1.main(...) refer to M1 of C1 and
calling M1()
in C2.main(...) refer to M1 of C2.
The invocation of M1 (with out any prefix, see the first line of each main()
), are not subjected to polymorphism as M1 in C1 does not get overrided by C2.
But calling from C2 refer to M1 of C2 as M1 of C2 is hide the one in C1.
Read more here.
EDIT: I've just re-read your question and just see the part about "good programming practise".
As I said, static method are not inherited but hidden so they are as good as different method.
From a code's point of view, they are completely different methods.
Let say.
C1 has static method M1.
C2 extends C1 and has static method M1.
C3 extends C2.
When call M1 (without prefix) from C1, you call C1.M1().
When call M1 (without prefix) from C2, you call C2.M1(). // derive but get hidden
When call M1 (without prefix) from C3, you call C3.M1(). // derive and no hidden
To specify which method, use class name like C1.M1()
, C2.M1()
and C3.M1()
(this will called C2.M1()
).
So this implementation allows static method to be reimplemented but only as a different method not as an overridden (or replacement) method.
Therefore, this usually no different from let say naming them differently like: C1_M()
and C2_M()
.
So you may ask, why bother having this feature? I don't really know. Perhaps allows a more flexible naming to method.
But there is usage (that might or might not be intented) that I used is polymorphism via reflection.
Since you can get and call a method by name using reflection, allowsing them to have a same name will enable polymorphism when do via reflection.
For example (rought code, may not run):
String aClsName = "C1"; // "C2";
Class aCls = Class.forName(aClsName);
Method aMth = aCls.getMethod("M1"); // M1 of C1 or C2 depends on the class name.
aMth.invoke(null);
OR
Object aObj = new C1(); // new C2();
Class aCls = aObj.getClass();
Method aMth = aCls.getMethod("M1"); // M1 of C1 or C2 depends on the class of the object.
aMth.invoke(null);
When think about it, I think Java has use this too (like, writeObject(...)
for serialization) so it may be intented.
So to conclude, hiding static method is not a good programming practice (Eclipse also recommend against it) but it can be useful in two cases, (1) to name the method exact what it suppose to do and (2) to polymorph it using reflection.
Hope this helps.