当前位置: 首页 > 面试题库 >

Java中的继承与静态

轩辕瑞
2023-03-14
问题内容

我不太明白为什么可以在Java中继承静态方法?

继承就像从基类继承,而Static属于Class而不是Object。

那么,如果静态仅属于该类,为什么它会滴入派生类呢?它不应该只与定义它的类一起使用吗?

继承静态方法是一种好的编程习惯吗?


问题答案:

在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.main(…)引用C1的M1并

M1()在C2.main(…)中调用是指C2的M1。

对M1的调用(不带任何前缀,请参见的第一行main())不会受到多态性的影响,因为C1中的M1不会被C2覆盖。

但是从C2调用将C2的M1称为C2的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())。

因此,此实现允许重新实现静态方法,但只能作为不同的方法来实现,而不能作为重写(或替换)方法。

因此,这通常与让它们像这样命名不同没有什么不同: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具有以下层次结构类: 这是C#中相同代码的(盲)重复: 当我执行Java代码时,我得到了C#返回的信息。 对我来说,C#的结果更有意义,因为引用B调用了它自己的方法。 Java设计者决定打印而不是打印的逻辑是什么?我的意思是,为什么引用B在C中使用覆盖方法?这种方法的优势是什么? 如何更改Java代码以像C#一样打印出来?我的意思是,我怎么教Java调用它使用的完全引用的方

  • 问题内容: 我想要以下设置: 这在Java中可能吗?怎么样?如果可以避免的话,我宁愿不使用实例变量/方法。 谢谢! 编辑: 常量是数据库表的名称。每个子对象都是一个微型ORM。 问题答案: 您无法完全按照自己的意愿去做。也许可以接受的折衷方案是:

  • 问题内容: 假设我有以下课程: 以及这两个子类: 和 我的问题是这两个子类从父类共享相同的静态curID成员,而不是拥有不同的成员。 所以,如果我这样做: r1,r2,r3的ID为0,1,2,而t1,t2,t3的ID为3,4,5。除了这些,我希望t1,t2,t3的值分别为0、1、2,即使用curID静态变量的另一个副本。 这可能吗?如何? 问题答案: 正如其他人已经写过的,静态成员已绑定到该类,因

  • 我正在用Java建模,并使用构建器模式。在许多情况下,一些共同成员是在父级中定义的,而其他成员则是在从父级继承的子级上定义的。一个例子如下: 如果删除,则在上得到相同的错误。看来我对静态嵌套类的继承有一个根本的误解。 为什么当返回时,编译器会抱怨方法不在中?有没有一种方法可以像我所尝试的那样,利用继承和这个构建器模式,允许在父级中定义公共成员,在子级中定义其他成员?

  • 问题内容: 继承和多态都构成IS- A关系吗?在运行时发生继承和“重写”多态性而在编译时发生“过载”多态性是真的吗?我之所以这样问,是因为许多论坛似乎给出了相互矛盾且常常令人困惑的答案。 谢谢! 问题答案: 对于问题的第一部分,我认为维基百科提供了一个很好的定义: 在面向对象的程序设计中,子类型多态或包含多态是类型理论中的一个概念,其中名称可以表示许多不同类的实例,只要它们与某个公共超类相关即可。

  • 假设我有以下课程: 这两个子类: 和 我的问题是,这两个子类共享来自父类的同一个静态curID成员,而不是拥有不同的成员。 因此,如果我这样做: r1,r2,r3的ID是0,1,2,t1,t2,t3的ID是3,4,5。而不是这些我希望t1,t2,t3有值0,1,2,即使用另一个复制的curID静态变量。 这有可能吗?怎么做?