不太明白为什么Java中静态方法可以继承?
继承就像从基类继承并且静态属于类而不是对象。
那么,如果静态仅属于类,为什么它会渗透到派生类? 难道它不应该留在定义它的类中吗?
继承静态方法是一种好的编程习惯吗?
最佳答案
在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().
如您所见,
在C1.main(...)中调用M1()
引用C1的M1和
在C2.main(...)中调用M1()
引用C2的M1。
M1 的调用(没有任何前缀,请参阅每个 main()
的第一行)不受多态性影响,因为 C1 中的 M1 不会被 C2 覆盖。
但是从 C2 调用会引用 C2 的 M1,因为 C2 的 M1 隐藏 C1 中的 M1。
了解更多 here .
编辑:我刚刚重新阅读了您的问题,刚刚看到有关“良好编程实践”的部分。
正如我所说,静态方法不是继承的而是隐藏的,因此它们与其他方法一样好。
从代码的角度来看,它们是完全不同的方法。
说吧。
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()
)。
因此,此实现允许重新实现静态方法,但只能作为不同的方法,而不是作为重写(或替换)方法。
因此,这通常与以不同方式命名它们没有什么不同,例如: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)使用反射对其进行变形。
希望这有帮助。
关于java - Java 中的继承与静态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1740528/