Java - 子类调用超级构造函数,该构造函数调用子类方法而不是它自己的方法

2024-01-02

我将从一个代码示例开始:

class A {
    public A() {
        f(); //When accessed through super() call this does not call A.f() as I had expected.
    }

    public void f() {} //I expect this to be called from the constructor.
}

class B extends A {
    private Object o;

    public B() {
        super();
        o = new Object(); //Note, created after super() call.
    }

    @Override
    public void f() {
        //Anything that access o.
        o.hashCode(); //Throws NullPointerException.
        super.f();
    }
}

public class Init {
    public static void main(String[] args) {
        B b = new B();
    }
}

这个程序抛出一个NullPointerException。当对象b进入其超类的构造函数时A并调用该方法f()被 B 类覆盖B.f()被称为,而不是A.f()这是我所期望的。

我认为超类不应该知道它是否被子类化,但是类肯定可以使用它来判断它是否被子类化?这背后的原因是什么?如果我真的想要的话有什么解决办法吗A.f()被调用而不是B.f()?

提前致谢。


跟进问题:

感谢您的回答。我现在明白为什么会这样,但这里有一个后续问题。也许我错了,但子类型化的一个原则是超类型不应该知道它已被子类型化。这种“机制”让类知道它是否已被子类化。考虑这个代码示例:

class A {
    private boolean isSubclassed = true;

    public A() {
        f(); //A.f() unsets the isSubclassed flag, B.f() does not.
        if(this.isSubclassed) {
            System.out.println("I'm subclassed.");
        } else {
            System.out.println("I'm not subclassed.");
        }
    }

    public void f() {
        this.isSubclassed = false;
    }
}

class B extends A {
    public B() {
        super();
    }

    @Override
    public void f() {}
}

public class Init {
    public static void main(String[] args) {
        new B(); //Subclass.
        new A();
    }
}

该程序的输出是:

I'm subclassed.
I'm not subclassed.

Here A知道它已被子类化。不知道是谁干的,但这并不重要。这是如何解释的呢?我是不是被误导了?


The NullPointerException发生这种情况是因为当您构造 B 的实例时,会调用父构造函数(在 A 中)。这个构造函数调用f()方法,但由于对象的实际类型是 B,因此被重写f()调用B中的方法。

@Override
public void f() {
    //Anything that access o.
    o.hashCode(); //Throws NullPointerException as o has not been initialised yet
    super.f();
}

这里的教训是永远不要在构造函数中调用可以被子类覆盖的方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java - 子类调用超级构造函数,该构造函数调用子类方法而不是它自己的方法 的相关文章

随机推荐

  • 如果小于则 MIPS 汇编分支

    我一直在开发一个非常基本的 MIPS 程序 用于计算门票销售的一些内容 我已经实现了所有功能 但是当我执行 IF 语句 blt gt 如果小于则分支 时 我遇到了一些错误 我将以下数据存储在临时寄存器中 t0 of VIP tickets
  • 如何禁用 ion-datetime 中的特定日期?

    我在用离子日期时间 https ionicframework com docs api components datetime DateTime 用于选择我的特定日期Ionic3 Angular应用 我想禁用某些特定日期ion dateti
  • 可以有多个“:root”选择器吗?

    在 TWBS 4 中 bootstrap css 有一个 root带有颜色变量的选择器 Can my 子样式表还有有一个 root选择器 用于我自己的变量 我正在猜测 root 可以像任何其他选择器一样被覆盖和添加 但我还没有找到任何讨论或
  • 动态创建方法中的 Ruby 动态参数

    我有以下类型的方法定义 method name foo method arguments bar baz method mandatory arguments quux gt true method body gt quux bar baz
  • JavaFX 8,带有复选框的列表视图

    我想创建一个简单的ListView 我发现我可以使用 setCellFactory 方法 但我不明白如何正确使用它们 到目前为止我有 myListView setCellFactory CheckBoxListCell forListVie
  • 使用替代语言代码的异步语音识别响应没有语言代码

    我正在尝试使用新的测试版替代语言功能 https cloud google com speech to text docs multiple languages允许在创建转录作业时提供一组语言 并返回检测到的语言以及该语言的转录结果 当我从
  • 如何访问新的浏览器选项卡

    瓦蒂尔菜鸟在这里 我正在尝试连接并操作新生成的浏览器选项卡 但对如何识别新选项卡有点困惑 这是我所拥有的 Windows 7 32 位 IE 10 红宝石 1 9 3 p392 TDM 32 4 5 2 本地宝石 瓦提尔 4 0 2 x86
  • JSF:如何不在验证消息中显示元素 id?

    我有一个简单的 JSF 表单 对输入文本进行了一些验证 就像是
  • jquery 自动完成下拉菜单是透明的

    我正在尝试在我的一个文本字段上使用 jquery 自动完成功能 除了下拉列表由于某种原因是透明的这一事实之外 一切似乎都正常 我链接了 jquery ui js 和 jquery ui css 两者都是版本 1 11 4 似乎可以正常加载值
  • 调度另一个 Substrate FRAME Pallet 中定义的函数

    我熟悉实现此问题标题中描述的目标的一种机制 在调用在另一个托盘中编写的外部 如 Sudo 托盘或实用程序托盘中定义的多重签名功能 跨托盘调度功能还有哪些其他选项 具体来说 我想包括一个托盘 托盘 A 作为Trait 另一个托盘 托盘 B 的
  • 使用 re.findall() 替换所有匹配项

    Using re findall 我已经设法返回字符串中正则表达式的多个匹配项 然而 我返回的对象是字符串中的匹配列表 这不是我想要的 我想要的是用其他东西替换所有匹配项 我尝试使用与您在 re sub 中使用的类似语法来执行此操作 如下所
  • 以正确的方式重用 setter 和构造函数中的验证逻辑

    我有一个类 其中的属性带有自定义设置器来执行验证 我也希望能够将该属性作为构造函数参数传递 并从构造函数中调用 setter 以重用验证逻辑 class Part object def init self pn self pn None s
  • 如何以编程方式切换 Chrome 的 FPS 仪表?

    经过搜索 我发现this https stackoverflow com questions 22038065 show fps meter chrome 33主题 但这就是如何通过用户界面启用 显示仪表 我想知道是否可以通过启用 禁用仪表
  • 在 Oracle 过程中的字符串中调用函数

    我使用 Oracle 10g 编写一个应用程序 我目前面临这个问题 我将 文件名 作为 varchar2 类型的参数 文件名可能包含的示例值是 TEST to char sysdate DDD 在该过程中 我想获取该文件名的值 如 TEST
  • 是否有使用频率对数除法的 FFT?

    维基百科的小波文章 http en wikipedia org wiki Wavelet Comparisons with Fourier Transform 28Continuous Time 29包含以下文字 离散小波变换的计算复杂度也
  • 如何在 R 中通过高效过滤和分组来对数据进行子集化

    我正在开发一个项目 正在寻求一些帮助以使我的代码运行更有效 我搜索过类似的问题 但似乎找不到像这个问题那么细致的问题 我想出的解决方案非常笨拙 我相信一定有一种更有效的方法来使用像这样的包来做到这一点dplyr data tables et
  • 查找与所有类别匹配的产品 (Rails 3.1)

    我正在努力处理 Rails 3 1 1 中的 ActiveRecord 查询 我有 2 个模型 产品和类别 从产品到类别有一个 has and belongs to many 一个产品可以有多个类别 我正在尝试编写一个搜索查询 它将找到具有
  • Jackrabbit Oak:入门并通过 RMI 连接到独立存储库

    我对长耳大野兔和长耳大野兔橡树完全陌生 不过 我与 Alfresco 进行了很多合作 这是另一个符合 JCR 的开源内容存储库 我想启动一个独立的 Jackrabbit Oak 存储库 然后通过 Java 代码连接到它 不幸的是 Oak 文
  • 使用 geom_smooth 将 glm 拟合到分数

    这篇文章有点相关这个帖子 https stackoverflow com questions 62974766 removing alpha transparency from ggplot legend and setting x axi
  • Java - 子类调用超级构造函数,该构造函数调用子类方法而不是它自己的方法

    我将从一个代码示例开始 class A public A f When accessed through super call this does not call A f as I had expected public void f I