在Java中,静态方法不是
继承
(或者正确的词是
重写的
)但他们可以
隐藏的
.
这里最大的不同是,它们不像对象方法那样受到多态性的影响。
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);
}
}
当运行
C2.main(null)
你会得到:
C2.M1().
C1.M1().
正如你所看到的,
打电话
M1()
在C1中,主(…)指C1中的M1和
打电话
M1()
在c2中,main(…)指c2中的m1。
调用m1(去掉任何前缀,请参见每个前缀的第一行
main()
)不受多态性的影响,因为c1中的m1不会被c2覆盖。
但从指挥控制系统呼叫时,将指挥控制系统的M1称为指挥控制系统的M1。
隐藏
C1中的那个。
编辑:
我刚刚重读了你的问题,只看到了关于“良好编程实践”的部分。
如我所说,静态方法不是继承的,而是隐藏的,所以它们和不同的方法一样好。
从代码的角度来看,它们是完全不同的方法。
比如说。
C1 has static method M1.
C2 extends C1 and has static method M1.
C3 extends C2.
当从c1调用m1(不带前缀)时,调用c1.m1()。
当从c2调用m1(不带前缀)时,调用c2.m1()。//派生但隐藏
当从c3调用m1(不带前缀)时,调用c3.m1()。//派生且不隐藏
要指定哪个方法,请使用类名称
C1.M1()
,
C2.M1()
和
C3.M1()
(这将调用
c2.M1()
)
因此,这个实现允许静态方法被重新实现,但只能作为一个不同的方法,而不能作为被重写(或替换)的方法。
因此,这通常与Let Say给它们命名不同,比如:
C1_M()
和
C2_M()
.
所以你可能会问,为什么要有这个功能?我真的不知道。可能允许对方法进行更灵活的命名。
但我使用的用法(可能是有意的,也可能不是有意的)是通过反射实现的多态性。
由于可以使用反射按名称获取和调用方法,因此允许它们具有相同的名称将在通过反射时启用多态性。
例如(粗糙代码,可能不运行):
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);
或
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);
当我想到它的时候,我想Java也会使用它。
writeObject(...)
用于序列化),因此可能有用意。
综上所述,隐藏静态方法并不是一个好的编程实践(Eclipse也建议不要这样做),但在两种情况下它是有用的:(1)精确地命名该方法应该做的事情;(2)使用反射对其进行变形。
希望这有帮助。