java - Java 中的继承与静态

标签 java oop

不太明白为什么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/

相关文章:

Java String 对象的相等性和引用

java - 分离对象中的 Hibernate 延迟加载

java - Spring 应用程序上下文 XML 的命名约定

java - 无法识别 IntelliJ : why my android. 支持包?

java - 从 FileChannel (Java NIO) 读取 GZIP 文件

python - 使用许多没有成员函数的子案例编写干净的 Julia 代码

javascript - 对象列表因某些别名而损坏

C# |= 和 &= 运算符

java - 类型中的方法不适用于参数

oop - 解释这张关于依赖倒置原则的励志海报