问题:在构造器里调用可重写的方法有什么问题?

我有一个检票页面的类通过抽象方法的结果去去设置页的标题

public abstract class BasicPage extends WebPage {public BasicPage() {add(new Label("title", getTitle()));}protected abstract String getTitle();}

NetBeans就警告我"Overridable method call in constructor"这个信息,但是这是什么错误鸭?
我能想到的唯一替代方案就将抽象方法的结果传递给子类的父类构造器,但是很多参数就无法读取了

回答一

下面有一个帮助你理解的例子

public class Main {static abstract class A {abstract void foo();A() {System.out.println("Constructing A");foo();}}static class C extends A {C() { System.out.println("Constructing C");}void foo() { System.out.println("Using C"); }}public static void main(String[] args) {C c = new C(); }
}

如果你跑一下上面的代码,就会得到下面的结果

Constructing A
Using C
Constructing C

看到了吗?foo()使用到了C,在C的构造函数开始跑之前。如果foo()要求c有一个确定的状态(构造函数已经完成了),那么就会遇到一个C未被定义的状态,就会直接失败了。因此你不能确定A里面可重写的foo()需要什么,你就会碰到一个警告了。

回答二

下面这个例子揭露了当在父类构造器中调用一个可重写的方法可能出现的逻辑问题

class A {protected int minWeeklySalary;protected int maxWeeklySalary;protected static final int MIN = 1000;protected static final int MAX = 2000;public A() {setSalaryRange();}protected void setSalaryRange() {throw new RuntimeException("not implemented");}public void pr() {System.out.println("minWeeklySalary: " + minWeeklySalary);System.out.println("maxWeeklySalary: " + maxWeeklySalary);}
}class B extends A {private int factor = 1;public B(int _factor) {this.factor = _factor;}@Overrideprotected void setSalaryRange() {this.minWeeklySalary = MIN * this.factor;this.maxWeeklySalary = MAX * this.factor;}
}public static void main(String[] args) {B b = new B(2);b.pr();
}

结果可能是:

minWeeklySalary: 0maxWeeklySalary: 0

这是因为B的构造器第一次调用A的构造器,B里面可重写的方法就会被执行。但是里面执行的方法需要使用到我们实例的变量,但是我们实例的变量还未被初始化(因为A的构造器还没完成执行),因为这个变量的值0,而不是1也没有被定义为2(程序员可能认为是这样的)。如果这种逻辑推导要干十多次的话,那就很难去追踪一个错误了

我希望这对你是有帮助的

文章翻译自Stack Overflow:https://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors

在构造器里调用可重写的方法有什么问题?相关推荐

  1. java draw 方法调用_java,_Java,在构造器里调用多态方法,java - phpStudy

    Java,在构造器里调用多态方法 class Glyph { void draw() { System.out.println("Glyph.draw()"); } Glyph() ...

  2. vue项目如何在data里调用methods中的方法

    vue项目如何在data里调用methods中的方法 比如使用swiper组件在data里调用methods中函数的方式:data在vue项目里实际也是个函数,所以只要如下操作就行: data() { ...

  3. java向上转型不能调用子类独有的方法

    向上转型只能够调用子类重写的方法,子类独有的方法在父类中根本没有定义,所以父类无法找到子类独有的方法. package com.company;public class Main {public st ...

  4. Java中关于子类重写父类方法的坑

    什么是方法重写? 设类B继承自类A.在A中定义方法了method_A,在B中定义方法了method_B.若method_B的签名等价于method_A的签名,则称B重写了A的method_A方法. 方 ...

  5. JSPatch实现原理详解:让JS调用/替换任意OC方法

    JSPatch实现原理详解:让JS调用/替换任意OC方法 2015-07-10 09:05 编辑: suiling 分类:iOS开发 来源:bang JSPatch以小巧的体积做到了让JS调用/替换任 ...

  6. java父类调用被子类重写的方法

    [转][原文]  1.如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解jav ...

  7. EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态...

    EF里查看/修改实体的当前值.原始值和数据库值以及重写SaveChanges方法记录实体状态 原文:EF里查看/修改实体的当前值.原始值和数据库值以及重写SaveChanges方法记录实体状态 本文目 ...

  8. Java调用被子类重写的方法

    Java调用被子类重写的方法 在访问权限允许的情况下,子类可以调用父类的方法,这是因为子类继承父类就会获得父类的定义的成员不变量和方法:但父类却不能调用子类的方法,因为父类无法知道会被什么子类所继承, ...

  9. 从java里调用r jri的设置方法_从Java里调用R – JRI的设置方法

    JRI允许用户从Java里面调用R的功能,而Eclipse是目前最常用的Java开发环境.本文介绍在Eclipse里设置JRI的方法. 环境: Windows 7 32bit Eclipse 3.6 ...

最新文章

  1. 关于网站购买商品的一些感悟
  2. 福建省计算机一级应用技术基础知识,求福建省计算机一级考试的基础题
  3. docker运行mywebsql
  4. ML 自学者周刊:第 4 期
  5. Javascript的对象继承方法
  6. APT 新组织利用 ASP.NET exploit 攻击微软 IIS 服务器
  7. 图像椒盐噪声和高斯噪声
  8. 对话阿里 CTO 程立:未来数字世界的根基是开源和云
  9. PLSql不用安装Oracle客户端,实现远程连接
  10. 英汉汉英词典,牛津高级词典,电子词典,离线英汉,汉英词典的使用方法
  11. 【精品整站】WordPress自适应美女写真网站源码/美图整站源码带数据/安装即可运营
  12. 高通骁龙200、400、600、800处理器规格分享
  13. 登录邮箱显示imap服务器错误,qq邮箱登陆不了显示imap服务器关闭怎么办
  14. CPU频率调节模式以及降频方法简介
  15. FB_LLC 死区时间计算(保证ZVS)
  16. git官网下载不了或下载很慢的解决办法!
  17. 计算机绘图图框实验报告,制图基础及计算机绘图实验报告.doc
  18. 【台大郭彦甫】Matlab入门教程超详细学习笔记二:基本操作与矩阵运算(附PPT链接)
  19. Corn fields(玉米田)状压dp入门第一题 洛谷P1879 poj3254
  20. 报数游戏(3)--【英雄会】

热门文章

  1. Linux 环境 C语言 操作MySql 的接口范例
  2. 单向循环链表C语言实现
  3. Mysql数据库简单使用(二)
  4. 万字长文!java读取json文件数据给对象
  5. Android开发;Activity-Hook你了解多少?一起来debug
  6. php用户之间的数据,什么是位于用户与操作系统之间的一层数据管理软件
  7. linux mysql 删除表脚本_linux shell脚本自动删除mysql表前3个月的数据
  8. 使用IDEA创建Maven项目和Maven使用入门(配图详解)
  9. Java开发中 Double 和 float 不能直接运算
  10. 扫盲丨关于区块链你需要了解的所有概念