再探Java中的继承加载顺序
来源:互联网 发布:2017年春运大数据 编辑:程序博客网 时间:2024/05/24 04:07
public class test2 { static class a { int x = 999; int y = 999; { System.out.println("a--父类非静态方法"); } static { System.out.println("a--父类静态方法"); } // public a() { // System.out.println("a--执行a类无参构造方法"); // } public a(int x) { System.out.println("a--执行父类有参构造方法"); } public void print() { System.out.println("a--我是父类的打印方法"); } } static class b extends a { int x = 1; int y; { System.out.println("b--子类非静态方法"); } static { System.out.println("b--子类静态方法"); } // public b() { // super(); // System.out.println("b--执行b类无参构造方法"); // //y = -1; // } public b(int x) { super(1); System.out.println("b--执行子类有参构造方法"); } public void print() { System.out.println("b--在子类中调用父类的super方法"); super.print(); System.out.println("b--我是子类的打印方法"); } } public static void main(String[] args) { // TODO Auto-generated method stub int x = 0; new b(x); //a.print(); }}
如图,这样加载顺序,先加载的都是静态块,先父类后子类。然后加载父类的非静态方法和构造器,然后子类的非静态方法和构造器
执行顺序大体上可以说是先父类后子类,父类static域 ==》子类static域 ==》父类数据成员域 ==》父类构造器 ==》子类数据成员域 ==》子类构造器。而且从结果中我们还可以看到,无论实例化多少个对象,static 域仅有一份,而且只执行一次。
注意第三十九行代码:这里显式调用了父类的有参构造,不加的话会默认调用无参的,如果父类没写无参的就会报错
第二个:
public class test1 { static class a { int x = 999; int y = 999; { System.out.println("a--父类非静态方法"); } static { System.out.println("a--父类静态方法"); } public a() { System.out.println("a--执行a类无参构造方法"); print(); } public a(int x) { System.out.println("a--执行父类有参构造方法"); } public void print() { System.out.println("a--我是父类的打印方法"); } } static class b extends a { int x = 1; int y; { System.out.println("b--子类非静态方法"); } static { System.out.println("b--子类静态方法"); } public b() { System.out.println("b--执行b类无参构造方法"); //y = -1; } public b(int x) { // super(1); //不写是默认生成的super(),无参数的 System.out.println("b--执行子类有参构造方法"); } public void print() { System.out.println("b--在子类中调用父类的super方法"); super.print(); System.out.println("b--我是子类的打印方法"); } } public static void main(String[] args) { // TODO Auto-generated method stub int x = 0; a a1 = new a(x); a1.print(); System.out.println(); b b1 = new b(x); // a.print(); } }
输出如图:
第二个声明了子类的对象,因为print(),在子类中被重写了。所以调用的是子类的重写后的print方法。但是还是可以通过super访问父类的这个被重写的方法。
子类的构造器必须要调用父类的构造器才能完成初始化,默认的是super(),没有参数的,也就是会默认调用父类无参数的构造器
第三个:
public class test1 { static class a { int x = 999; int y = 999; { System.out.println("a--父类非静态方法"); } static { System.out.println("a--父类静态方法"); } // public a() { // System.out.println("a--执行a类无参构造方法"); // print(); // } public a(int x) { System.out.println("a--执行父类有参构造方法"); } public void print() { System.out.println("a--我是父类的打印方法"); } } static class b extends a { int x = 1; int y; { System.out.println("b--子类非静态方法"); } static { System.out.println("b--子类静态方法"); } public b() { super(0); System.out.println("b--执行b类无参构造方法"); //y = -1; } public b(int x) { super(1); //不写是默认生成的super(),无参数的 System.out.println("b--执行子类有参构造方法"); } public void print() { System.out.println("b--在子类中调用父类的super方法"); super.print(); System.out.println("b--我是子类的打印方法"); } } public static void main(String[] args) { // TODO Auto-generated method stub int x = 0; // a a1 = new a(x); // a1.print(); System.out.println(); b b1 = new b(x); // a.print(); } }
如果注释了父类的无参构造,但是子类还有有无参构造,我现在创建的是子类有参的对象,还是会报错。为什么?问了杨学长,语法规定就是这样,就算这个b子类无参构造没有实际加载(打印信息没有打印),只要你写了子类的构造,你就必须要为这个构造方法负责,不管在之后对象有没有用到。注释了父类无参构造的话,可以在b子类无参构造这里加一个super(0),调用父类有参的构造,必须要特别这样声明才行,不声明编译器会找父类无参,无参又没有,所以报错。
编译器按照Java语言的规范把源码编译成字节码文件,然后JVM加载这个类,初始化等一系列操作调用它的main方法。所以说编译的时候会检查你的语法是否正确,不是说不用就检查了,编译时能发现的错误,不会拖延到运行时才知道
- 再探Java中的继承加载顺序
- Java中的继承关系的加载顺序
- java 继承类加载顺序
- Java中的继承初始化顺序
- Java继承和静态-加载顺序
- Java中的类加载顺序
- Java的继承及继承中类的加载顺序
- Java的继承及继承中类的加载顺序
- JAVA继承关系中的初始化顺序
- Java类继承关系中的初始化顺序
- Java 继承加载顺序 以及 多态中变量和方法
- Java的继承中类的加载顺序
- java基础:继承关系类加载顺序问题
- java继承各个类构造器加载的顺序
- 继承中的访问顺序
- 继承中的初始化顺序
- 继承中的初始化顺序
- java中的继承,继承中方法的重写,继承的初始化顺序,final关键字,super关键字
- 我眼中的设计模式(8)
- eclipse如何自动添加函数
- 1197
- 小巴学车有关项目的总结
- Thrift入门介绍
- 再探Java中的继承加载顺序
- mysql的历史命令记录,~/.mysql_history
- HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)
- 小米品牌广告引擎与算法实践
- 图片和文字完美结合
- 如何发布Web项目到互联网
- 康复计划#2 常用基础数论知识杂烩
- 4-安卓底层-HAL层-实现安卓控制LED
- Linux环境安装SVN