引例

public class A extends B {

public int a = 100;

public A() {

super();

System.out.println(a);

a = 200;

}

public static void main(String[] args) {

System.out.println(new A().a);

}

}

class B {

public B() {

System.out.println(((A) this).a);

}

}

例子代码很简单,不多做解释了,直接看输出:

0

100

200

对照这个输出,我们来详细分析一下对象的初始化顺序:

为A类分配内存空间,初始化所有成员变量为默认值,包括primitive类型(int=0,boolean=false,…)和Reference类型。

调用A类构造函数。

调用B类构造函数。

调用Object空构造函数。(java编译器会默认加此构造函数,且object构造函数是个空函数,所以立即返回)

初始化B类成员变量,因为B类没有成员变量,跳过。

执行sysout输出子类A的成员变量小a。// 此时为0

初始化A类成员变量,将A类成员变量小a赋值100。

执行sysout输出当前A类的成员变量小a。// 此时为100

赋值当前A类的成员变量小a为200。

main函数中执行sysout,输出A类实例的成员变量小a。// 此时为200

加粗的那两行描述是重点,结论是成员变量初始化是在父类构造函数调用完后,在此之前,成员变量的值均是默认值。 Dzone作者就是栽在这里,没有仔细分析成员变量初始化在对象初始化中的顺序,造成了程序未按原意执行。

其实这类问题,熟悉原理是一方面,本质上只要不在构造函数中插入过多的业务逻辑,出问题的概率也会低很多。

类加载简单时序图

程序的输出是什么?

public class Base {

private String baseName = "base";

public Base() {

callName();

}

public void callName() {

System.out.println(baseName);

}

static class Sub extends Base {

private String baseName = "sub";

@Override

public void callName() {

System.out.println(baseName);

}

}

public static void main(String[] args) {

Base b = new Sub();

}

}

有了前面的引例,这道题答案就比较简单了

答案: null

public class Demo {

class Super {

int flag = 1;

Super() {

test();

}

void test() {

System.out.println("Super.test() flag=" + flag);

}

}

class Sub extends Super {

// int flag;

Sub(int i) {

flag = i;

System.out.println("Sub.Sub()flag=" + flag);

}

@Override

void test() {

System.out.println("Sub.test()flag=" + flag);

}

}

public static void main(String[] args) {

new Demo().new Sub(5);

}

}

答案:

Sub.test()flag=1

Sub.Sub()flag=5

在我刚做这道题的时候也是有不少疑惑

为什么输出会是 1, 5 不应该是 0, 5

因为覆写了,没有指明 super 调用父类方法,父类的方法怎么都不可能被调用

所以自己打断点查找原因得到一个规律

我将构造函数的执行化为 三个阶段

class Super {

int flag = 1; // ②

Super() { // ①

test(); // ③

}

void test() {

System.out.println("Super.test() flag=" + flag);

}

}

通过这个规律,我将注释写在先前的代码上

public class Demo {

class Super {// ③ 除 Object 无继承,开始执行构造函数

int flag = 1; // ⑤ 加载成员变量完毕

Super() { // ④ 程序运行到这里的时候,开始加载成员变量

test(); // ⑥ 调用子类方法

}

void test() {

System.out.println("Super.test() flag=" + flag);

}

}

class Sub extends Super {// ② Sub 类有父类,继续寻找

Sub(int i) { // ⑧ 开始加载子类的构造函数

flag = i; // ⑨ 重新对父类变量 flag 赋值

System.out.println("Sub.Sub()flag=" + flag); // ⑩ 对父类变量进行输出

}

@Override

void test() {

System.out.println("Sub.test()flag=" + flag); // ⑦ 输出父类的变量 flag

}

}

public static void main(String[] args) {

new Demo().new Sub(5); // ① 开始寻找 Sub 类

}

}

PS: 这些都是简单题,还有静态变量,静态类,内部类,内部静态类,内部静态类静态变量 try catch finally return 各种混合...

java类的加载顺序题目_Java 类的加载顺序(题)相关推荐

  1. java类的两个基本成分_Java类文件的基本结构

    欢迎来到""第二期.我们讨论了抽象计算机JVM.如果你对JVM还很陌生,你可以去看看.本期,我们稍稍窥探一下Java类文件的基本结构. 为旅行而生 Java类文件(.class文件 ...

  2. java类与对象 编程题目_Java类与对象的课后练习

    Java类与对象的课后练习编程题(java2实用教程P111) 这章内容自学完了,在做教材课后其他练习题的时候(只要自己仔细)都没啥问题,但在做最后一道上机编程题的时候问题出现了,在阅读题目的时候自己 ...

  3. java 执行顺序混乱_java类执行顺序问题

    经常遇到的面试题,一个类继承另一个类然后问输出的结果是什么.个人觉得就是考类的输出问题(亲测) 第一:单一的类执行顺序 package Test; public class person { stat ...

  4. java 类及对象的课后作业_JAVA类和对象课后作业

    1.使用类的静态字段和构造函数,我们可以跟踪某个类所创建对象的个数.请写一个类,在任何时候都可以向它查询"你已经创建了多少个对象?" 代码: //显示类 //YiMingLai 2 ...

  5. java类的修饰词有哪些_Java类与对象及访问控制修饰词解析

    Java 是个纯面向对象语言,不支持过程式编程,所有操作都是基于对象. 一.类 类是 Java 中的一种引用数据类型,引用数据类型值都存储在堆中.类是构造对象的模板,每个类对象都是类通过 new 语句 ...

  6. java 图片加水印不失真_java实现图片加水印效果

    图片加水印代码,这些代码不常用,但是用到的时候需要注意的地方也挺多的,每次都重写比较麻烦,记下来备忘.代码是图片加水印的一般流程,可根据实际项目需要自行修改. 注:代码在JPG和PNG格式图片下测试通 ...

  7. java设计狗叫和狗咬_Java类谜题47:啊呀!我的猫变成狗了

    面的程序使用了一个Counter类来跟踪每一种家庭宠物叫唤的次数.那么该程序会打印出什么呢? class Counter { private static int count = 0; public ...

  8. java嵌套类中的方法怎么调用_java类与嵌套嵌套后,怎么使用最外层的类建立对象后使用内部类的方法?...

    展开全部 /* package whatever; // don't place package name! */ import java.util.*; import java.lang.*; im ...

  9. 学习java要学类与对象的使用吗_java 类与对象 的概念理解(可以用我们学习多年的蚂蚁哲学套用)...

    面向对象其实是一种思考的思想,是解决问题,架构工程的整体解决方案.二早期编程语言的思想是面向过程. 面向过程注重的是过程,过程所涉及的行为,也就是功能.通过选择循环语句等逻辑将参与者连接起来. 面向对 ...

最新文章

  1. 120万公里「真」无人商用里程如何炼成?出租车物流车车车无人,香港乌鲁木齐城城自动...
  2. CString与LPCWSTR、LPSTR、char*、LPWSTR等类型的转换【转】
  3. 10个快速提升技术水平的方法
  4. Robot Framework 教程 (3) - Resource及关键字 的使用
  5. 拼智商,谷歌、苹果、微软、亚马逊的AI助手谁赢了?有些结果没料到
  6. 图解深度学习的笔记:1.MP模型,感知器,BP下的多层感知器
  7. Appium原理及使用
  8. 学习C语言——字母金字塔
  9. edp协议 netty_使用esp8266 arduino 通过EDP协议 将数据传递到onenet平台
  10. 使用UE4创建一个简单真实的地球(一)
  11. 字节输入输出流,字符输入输出流
  12. xxl-job配置发邮件 spring.mail的QQ邮箱配置
  13. java使用poi生成Excel文件并合并单元格
  14. JavaScript中内存溢出和内存泄漏
  15. Cocos Creator基于热更新的分包方案
  16. 史上最牛最强的linux学习笔记 7.用户和用户组管理
  17. 用python画正方形
  18. SA(需求分析师)笔试题目整理
  19. php判断用户和管理员,php – 检查用户是否是root用户
  20. 论国产PLC产业化发展

热门文章

  1. Android Studio Design界面不显示layout控件的解决方法
  2. 【实践】端智能在大众点评搜索推荐重排序的应用实践
  3. 广告深度预估技术在美团到店场景下的突破与畅想
  4. 【报告分享】2021新青年国货消费研究报告:文化觉醒时代,宝藏国货迎复兴机遇.pdf(附下载链接)...
  5. 【报告分享】转变与机遇:从京东大数据看2020消费市场与品牌成长.pdf(附下载链接)...
  6. 电商场景中的精排服务实践
  7. mysql意外关机_MySQL服务器意外关机-无法启动多实例
  8. tiktok跨境出海?
  9. Leetcode每日一题:24.swap-nodes-in-pairs(两两交换链表中的节点)
  10. 给PhotoShop安装Portraiture插件