java构造方法不允许调用重载方法

今年在搭建一个项目的基础架构的时候,遇到了一个问题,一个类的初始化对象总是得到错误的数据,从常规语法上不到赋值错误。java代码大概如下:

import org.junit.Test;public class ConstructorInvokeOverrideTest {@Testpublic void test() {new FlowView(1234);}class FlowView extends BaseView {int layoutId;public FlowView(/*Context context, */ int layoutId) {super(/*context*/);this.layoutId = layoutId;}@Overrideprotected int getLayoutId() {return layoutId;}}abstract class BaseView {BaseView(/*Context context*/) {inflate(getLayoutId());}public void inflate(int layoutId) {System.out.println("layoutId: " + layoutId);}protected abstract int getLayoutId();}
}

输出结果

layoutId: 0

按照设计思路,此处应该是打印layoutId:1234。可是事与愿违,打印的是layoutId。因为实际代码行数很多,当时模块比较多,一直以为是其他模块的初始化导致的,然后叫坐在身边的同事一起review代码,对方也没看出个所以然(这里告诉大家一个查bug的技巧,在实战中,交叉review是非常高效的解决问题方法,可以排除一些常规的低级错误,与开发人员双方水平无关)

范例说明:

1. 在实际代码中,一直是抛出异常;

2. 为了避嫌避免泄漏商业代码,构造函数并非是layoutId,重载的函数也不是getLayoutId();

3. Context是在Android中的一个上下文句柄,此处代码为了简洁,我们忽略掉该初始化参数,加上注释的原因是为了让读者更好理解实际继承时是有初始化参数的。

问题原因:

对于这个问题,只能推翻重来,把本次修改的内容一点点回退。最终发现原来犯了一个语法错误。

1. FlowView中定义了成员变量layoutId;

2. BaseView的getLayoutId是一个可以重载的方法;

3. FlowView继承并覆盖了getLayoutId并且BaseView的构造函数中调用了getLayoutId;

那么就导致一个问题,父类在构造函数调用继承重载方法时,子类并没有完成实例化(因为父类和子类的构造函数还没有执行完),子类FlowView成员变量layoutId可能还没有完成初始化。

发现这个问题后,一百度,果然很多人犯过在构造方法中调用重载方法的错误。修改这个问题也很简单,在构造函数中不调用重载方法。

另外,BaseView的getLayoutId是一个抽象方法。即使不用抽象方法,结果还是一样。

public class ConstructorInvokeOverrideTest {@Testpublic void test() {new FlowView(1234);}class FlowView extends BaseView {int layoutId;public FlowView(/*Context context, */ int layoutId) {super(/*context*/);this.layoutId = layoutId;}@Overrideprotected int getLayoutId() {return layoutId;}}// no abstract class.class BaseView {BaseView(/*Context context*/) {inflate(getLayoutId());}public void inflate(int layoutId) {System.out.println("layoutId: " + layoutId);}protected int getLayoutId() {return -1;}}
}

输出结果:

layoutId: 0

注意:是0,而不是-1。 因为getLayoutId()已经被重载覆盖了。

最后,输出结果可能在Oracle JDK18和Android上面的结果可能不一样。

本博客的运行环境是:

java version "1.8.0_152"

Java(TM) SE Runtime Environment (build 1.8.0_152-b16)

Java HotSpot(TM) 64-Bit Server VM (build 25.152-b16, mixed mode)

java构造方法不允许调用重载方法相关推荐

  1. java方法调用原则,Java 中,在调用重载方法时,原则是(   )。_学小易找答案...

    [多选题]20世纪80年代后,国外企业伦理学进入了全面发展阶段,主要表现在( ). [判断题]扩展库numpy的isclose()和allclose()用来测试两个数组是否严格相等. [单选题]以下市 ...

  2. android 反射调用方法可不可以重载,使用Java进行反射投射和重载方法调度

    请注意,所有代码都是一个简化示例,目的是仅传达我的问题的核心思想.它应该都经过轻微的编辑后编译并运行.使用Java进行反射投射和重载方法调度 我有几个类都实现了一个通用接口. public inter ...

  3. java:PropertyDescriptor+反射调用setter方法

    java:PropertyDescriptor+反射调用setter方法 1 前言 PropertyDescriptor文档如下: https://docs.oracle.com/javase/7/d ...

  4. java高级用法之:调用本地方法的利器JNA

    文章目录 简介 JNA初探 JNA加载native lib的流程 本地方法中的结构体参数 总结 简介 JAVA是可以调用本地方法的,官方提供的调用方式叫做JNI,全称叫做java native int ...

  5. Java 多线程启动为什么调用 start() 方法而不是 run() 方法?

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:终于放弃了单调的swagger-ui了,选择了这款神器-knife4j个人原创100W+访问量博客:点击前往,查 ...

  6. java finalize 何时被调用_finalize()方法什么时候被调用?析构函数(final

    finalize()方法也叫收尾方法. 一旦垃圾回收器准备好释放对象占用的存储空间,首先会去调用finalize()方法①进行一些必要的清理工作(对垃圾回收器不能处理的特殊情况进行处理)(例子在下边) ...

  7. java构造方法何时被调用_构造方法何时被调用

    在java语言中,构造函数又称构造方法. 构造函数的作用是初始化对象,即在创建对象时被系统调用(与普通方法不同,程序不能显示调用构造函数).构造函数还能够被重载,即可以传入参数,当程序中包含有带参的构 ...

  8. java构造方法的互相调用

    public Student(int age){super();this.age = age; }public Student(String name , int age){/*super(); 注意 ...

  9. Java构造方法的继承调用

    1.对于父类含有参数构造函数的方法,子类可以通过在自己构造方法中使用super关键字来调用,但是super必须是第一个可执行语句 2.父类无参构造函数一定被调用 class Father{public ...

  10. java关闭通道_调用map方法后,Java 7文件通道未正确关闭

    我正在研究一个sc2replay解析工具.我在MPQLIB http://code.google.com/p/mpqlib/之上构建它 不幸的是,该工具使用文件通道来读取bzip文件, 并使用map( ...

最新文章

  1. 关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序。
  2. mysql导出长数字到excel避免显示为科学记数法 解决方法
  3. DBA表现最好的7个习惯
  4. 企业级应用WebLogic11g集群配置与项目实施_WebLogic部署培训教程
  5. 【收藏】docker安装redis
  6. android 并排按钮,简单布局:右边三个按钮并排靠右,左边一个输入框填满其他空间,多谢...
  7. asp.net core 中使用 signalR(二)
  8. 对对象类型和调用方法属性进行存储以提升反射性能
  9. 阿里云数据库8月刊:国内首款Cloud Native自研数据库POLARDB精彩亮相VLDB!
  10. 【事件驱动】【数码管识别】 封装成DLL的函数的梳理
  11. 常用关系型数据库管理系统
  12. Ubuntu18.04安装英伟达显卡驱动
  13. 如何给PDF加水印?PDF加水印教程
  14. Linux——shell脚本的基础篇(变量定义、变量种类、变量操作)
  15. Java第七周心得体会
  16. Bypass-分流抢票
  17. 【SCAU 新生赛】18247 aler的旅游计划 并查集模板题
  18. RTX3080 Ti 怎么样 RTX3080 Ti性能相当于什么水平
  19. 所有API接口分类,淘宝/天猫API、1688API、拼多多API、京东API、各大电商API接口及测试平台
  20. java结束if_java中如何结束if循环

热门文章

  1. 2017_9_20 生活记录
  2. python中去除列表重复元素的方法汇总
  3. 【14年浙江省赛 F ZOJ 3781】Paint the Grid Reloaded 【建图、bfs】
  4. 牛顿插值 | MATLAB源码
  5. scala 主构造函数_Scala主构造器和辅助构造器
  6. Hershell:跨平台反向Shell生成器
  7. oracle服务器cpu 100,Oracle数据库服务器CPU一直100%怎么处理-sql优化方面
  8. 团队项目——测试心得
  9. STS热部署,springboot项目中修改代码不用重新启动服务
  10. UML统一建模语UML2和EnterpriseArchitect