文档章节

Java 父类子类的对象初始化过程

SimpleOne
 SimpleOne
发布于 2014/04/28 21:57
字数 1205
阅读 4825
收藏 11

1. 基本初始化过程:

对于一个简单类的初始化过程是:

    static 修饰的模块(static变量和static 块)  ---> 按照代码顺序依次执行。

        |

    实例变量  及非static模块---> 按照代码顺序依次执行。

        |

    构造函数 ---> 执行对应的构造函数。

子类的初始化过程。

    父类static修饰的模块

        |

    子类static修饰模块

        |

    父类实例变量和非static块

        |

    父类对应构造函数。当子类对应构造函数中没有显示调用时调用的是父类默认的构造函数。

        |

    子类实例变量和非static块

        |

    子类构造函数


Class的static模块是唯一的,所以只初始化一次。所有类的实例公用Class的static模块。

static模块的初始化条件: ( From: 引用1 )

    (1)遇到new、getstatic、putstatic 或 invokestatic这4条字节码指令时,如果类还没初始化,则触发初始化。对应场景是:new实例化对象时、读或设置一个静态字段时(被final修饰,已在编译器把结果放入常量池的静态字段除外),以及调用一个类的静态方法时

    (2)对类进行反射调用时

    (3)初始化子类。但父类还没有初始化时,先触发父类初始化

    (4)当虚拟机启动时,需指定一个需要执行的主类(包含main方法),虚拟机会先初始化该类



2. 关于覆盖和隐藏

    覆盖:被覆盖的方法相当于被擦除了,不可恢复(即使类型强制转换也无法调用)。

    隐藏:一直保存的某个位置,等需要的时候可以继续使用(类型强制转换后可以调用)。

关于父类子类之间的覆盖和隐藏关系: (From :引用2)

    1. 父类的实例变量和类变量能被子类的同名变量隐藏。 

    2. 父类的静态方法被子类的同名静态方法隐藏,父类的实例方法被子类的同名实例方法覆盖。 

    3. 不能用子类的静态方法隐藏父类的实例方法,也不能用子类的实例方法覆盖父类的静态方法,否则编译器会异常。 

    4. 用final关键字修饰的最终方法不能被覆盖。 

    5. 变量只能被隐藏不会被覆盖,子类的实例变量可以隐藏父类的类变量,子类的类变量也可以隐藏父类的实例变量。 


涉及的典型情况:

前提:

-----------------------------------------

class B extends A{……}

-----------------------------------------

(1) B instanceB = new B();

instanceB的初始化过程如第一部分中:子类的初始化过程。

此时instanceB中实际上有一个super的全部信息(除了父类中被覆盖的实例方法),但是当前的引用是子类的信息(如果子类中没有的变量和方法则是从父类继承来)。


(2)A instanceA = new B();

此时父类A的变量和静态方法会将子类的变量和静态方法隐藏。instanceA此时唯一可能调用的子类B的地方就是子类B中覆盖了父类A中的实例方法。

执行 B instanceB = (B) instanceA; 后

此时instanceB相当于 B instanceB = new B();


注意:

    (1) 这里唯一的覆盖的情况:父类的实例方法被子类的同名实例方法覆盖。

    这里方法调用变量时,实际上是带有一个默认的this的。也就是此实例方法中调用的是当前Class的值。涉及到继承的情况时,要十分注意super,this的情况。

    (2) 在初始化的时候,有两个阶段。第一步是申请空间,第二步是赋值。

    具体见:

        static的值和final static值在初始化时的区别。(引用1)

        子类覆盖父类实例方法时,调用子类的实例方法,而此时子类的实例方法调用了子类中的变量(此时static变量已经初始化,但是实例变量并没有初始化)。(引用2)


这段代码来自引用2,如何精炼,如此有趣。值得一看。

class Parent{
         int x=10;
         public Parent(){
              add(2);
         }
         void add(int y){
              x+=y;
         }
    }
     class Child extends Parent{
         int x=9;
         void add(int y){
              x+=y;
         }
         public static void main(String[] args){
              Parent p=new Child();
              System.out.println(p.x);
         } 
    }



引用 1. 类加载机制:

http://blog.csdn.net/kai_wei_zhang/article/details/8234146 

引用 2. 隐藏和覆盖,以及一个好例子:

http://www.cnblogs.com/binjoo/articles/1585342.html

引用 3. 隐藏和覆盖

http://renyanwei.iteye.com/blog/258304 

引用 4. 基本的初始化过程

http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html 

© 著作权归作者所有

SimpleOne
粉丝 3
博文 17
码字总数 18224
作品 0
烟台
程序员
私信 提问
加载中

评论(1)

SimpleOne
SimpleOne 博主
TODO:分析下面的情况:
Parent parent = (Parent) new Child();
貌似是隐藏了Child的静态变量和实例变量,但是方法仍然调用Child的。
方法和直接调用的变量值是不同的,因为方法是调用了本身类的this.variable。所以即使parent.variable是父类的值,但是parent.method()仍然调用Child里面的实例变量值(一切都是因为方法里调用实例变量时隐含了this.)。
Java类加载及变量初始化过程

Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就是解决上面3个问题的。 本文前...

kalo
2014/09/29
4.3K
0
【java基础☞初始化顺序】java继承中的初始化顺序

1、初始化顺序:父类的静态变量-->父类的静态代码块-->子类的静态变量-->子类的静态代码快-->父类的非静态变量(父类的非静态代码块)-->父类的构造函数-->子类的非静态变量(子类的非静态代码...

卯金刀GG
06/25
24
0
java对象和内存的控制深入浅出

一、对象与内存控制的知识点 1.java变量的初始化过程,包括局部变量,成员变量(实例变量和类变量)。 2.继承关系中,当使用的对象引用变量编译时类型和运行时类型不同时,访问该对象的属性和...

zhoulc
2013/06/18
1K
3
深入理解Java类的初始化顺序

Java类加载机制中最重要的就是程序初始化过程,其中包含了静态资源,非静态资源,父类子类,构造方法之间的执行顺序。这类知识经常会出现在面试题中,如果没有搞清楚其原理,在复杂的开源设计...

郑加威
06/03
35
0
Java和Android ClassLoder对比以及Class加载过程

Java的ClassLoder的父子关系如下:Bootstrap--ExtClassClassLoader---AppClassLoader。 JVM启动时先运行启动类加载器Bottstrap,主要加载Java核心API;然后加载扩展类加载器ExtClassLoder,该...

JasmineBen
2018/05/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OpenStack 简介和几种安装方式总结

OpenStack :是一个由NASA和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenSta...

小海bug
昨天
5
0
DDD(五)

1、引言 之前学习了解了DDD中实体这一概念,那么接下来需要了解的就是值对象、唯一标识。值对象,值就是数字1、2、3,字符串“1”,“2”,“3”,值时对象的特征,对象是一个事物的具体描述...

MrYuZixian
昨天
6
0
数据库中间件MyCat

什么是MyCat? 查看官网的介绍是这样说的 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵...

沉浮_
昨天
6
0
解决Mac下VSCode打开zsh乱码

1.乱码问题 iTerm2终端使用Zsh,并且配置Zsh主题,该主题主题需要安装字体来支持箭头效果,在iTerm2中设置这个字体,但是VSCode里这个箭头还是显示乱码。 iTerm2展示如下: VSCode展示如下: 2...

HelloDeveloper
昨天
7
0
常用物流快递单号查询接口种类及对接方法

目前快递查询接口有两种方式可以对接,一是和顺丰、圆通、中通、天天、韵达、德邦这些快递公司一一对接接口,二是和快递鸟这样第三方集成接口一次性对接多家常用快递。第一种耗费时间长,但是...

程序的小猿
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部