在构造器里调用可重写的方法有什么问题?
问题:在构造器里调用可重写的方法有什么问题?
我有一个检票页面的类通过抽象方法的结果去去设置页的标题
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
在构造器里调用可重写的方法有什么问题?相关推荐
- java draw 方法调用_java,_Java,在构造器里调用多态方法,java - phpStudy
Java,在构造器里调用多态方法 class Glyph { void draw() { System.out.println("Glyph.draw()"); } Glyph() ...
- vue项目如何在data里调用methods中的方法
vue项目如何在data里调用methods中的方法 比如使用swiper组件在data里调用methods中函数的方式:data在vue项目里实际也是个函数,所以只要如下操作就行: data() { ...
- java向上转型不能调用子类独有的方法
向上转型只能够调用子类重写的方法,子类独有的方法在父类中根本没有定义,所以父类无法找到子类独有的方法. package com.company;public class Main {public st ...
- Java中关于子类重写父类方法的坑
什么是方法重写? 设类B继承自类A.在A中定义方法了method_A,在B中定义方法了method_B.若method_B的签名等价于method_A的签名,则称B重写了A的method_A方法. 方 ...
- JSPatch实现原理详解:让JS调用/替换任意OC方法
JSPatch实现原理详解:让JS调用/替换任意OC方法 2015-07-10 09:05 编辑: suiling 分类:iOS开发 来源:bang JSPatch以小巧的体积做到了让JS调用/替换任 ...
- java父类调用被子类重写的方法
[转][原文] 1.如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解jav ...
- EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态...
EF里查看/修改实体的当前值.原始值和数据库值以及重写SaveChanges方法记录实体状态 原文:EF里查看/修改实体的当前值.原始值和数据库值以及重写SaveChanges方法记录实体状态 本文目 ...
- Java调用被子类重写的方法
Java调用被子类重写的方法 在访问权限允许的情况下,子类可以调用父类的方法,这是因为子类继承父类就会获得父类的定义的成员不变量和方法:但父类却不能调用子类的方法,因为父类无法知道会被什么子类所继承, ...
- 从java里调用r jri的设置方法_从Java里调用R – JRI的设置方法
JRI允许用户从Java里面调用R的功能,而Eclipse是目前最常用的Java开发环境.本文介绍在Eclipse里设置JRI的方法. 环境: Windows 7 32bit Eclipse 3.6 ...
最新文章
- 关于网站购买商品的一些感悟
- 福建省计算机一级应用技术基础知识,求福建省计算机一级考试的基础题
- docker运行mywebsql
- ML 自学者周刊:第 4 期
- Javascript的对象继承方法
- APT 新组织利用 ASP.NET exploit 攻击微软 IIS 服务器
- 图像椒盐噪声和高斯噪声
- 对话阿里 CTO 程立:未来数字世界的根基是开源和云
- PLSql不用安装Oracle客户端,实现远程连接
- 英汉汉英词典,牛津高级词典,电子词典,离线英汉,汉英词典的使用方法
- 【精品整站】WordPress自适应美女写真网站源码/美图整站源码带数据/安装即可运营
- 高通骁龙200、400、600、800处理器规格分享
- 登录邮箱显示imap服务器错误,qq邮箱登陆不了显示imap服务器关闭怎么办
- CPU频率调节模式以及降频方法简介
- FB_LLC 死区时间计算(保证ZVS)
- git官网下载不了或下载很慢的解决办法!
- 计算机绘图图框实验报告,制图基础及计算机绘图实验报告.doc
- 【台大郭彦甫】Matlab入门教程超详细学习笔记二:基本操作与矩阵运算(附PPT链接)
- Corn fields(玉米田)状压dp入门第一题 洛谷P1879 poj3254
- 报数游戏(3)--【英雄会】