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

摘要

Java基本的对象初始化过程,子类的初始化,以及涉及到父类和子类的转化时可能引起混乱的情况。

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

时间: 2024-12-20 06:24:54

Java父类子类的对象初始化过程的相关文章

java中类的创建及初始化过程

java中类的创建及初始化过程无外乎两种情况,其一为单类的创建及初始化,其二具有继承关系的父子类创建及初始化过程.     首先说简单的,单类的创建及初始化过程.在java中我们都知道绝大部分对象的创建时通过new 这个关键字来完成,当我们在自己的代码中写上       new ClassName()://创建 ClassName类的一个实例时,解释器当截取new这个关键字时,就会为ClassName量身定做一个内存空间,这个时候也就是为该类中的所有成员变量分配内存空间之时,并对其进行最原始的初

C#类对象初始化过程

C#类实例的初始化是这样进行的:在调用构造函数的入口处先初始化自身数据成员,若声明字段时显式给出了初始化语句则按初始化语句进行,否则若是基本类型例如int或string则初始化为0或"",若是类则保持为null:若该类含有基类则下一步调用基类构造函数,基类构造函数的执行过程同上,最后调用派生类构造函数的函数体. 以上过程纯属自己的验证加猜测. C#成员初始化列表中只能对base进行初始化. C#的初始化和C++有点不一样啊,似乎还更加隐晦,派生类的成员初始化为什么要比基类更早.感觉越是

[Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类

目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式在内存中存放对象: (1)为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定,这可以通过将对象置于堆栈或者静态存储区域内来实现.这种方式牺牲了灵活性. (2)在被称为堆的内存池中动态地创建对象.在这种方式,知道运行时才知道对象需要多少对象,它们的生命周期如何,以及它们的具体类型.

【深入理解Java虚拟机】类的初始化过程

类的初始化过程 类的加载过程.png 加载 将 Class 文件以二进制的形式加载到内存中 验证 校验 Class 文件是否安全,是否被正确的修改等 准备 为类变量申请内存,设置默认值,(初始化变量的默认值,比如int初始化为0,reference初始化为null) 但是达到类的初始化之前都没有初始化为真正的值. 零值.png 解析 将符号引用转换为直接引用 初始化 搜集并执行static代码块,以及 方法的执行, 是静态变量以及static 代码块组成 使用 为新对象申请内存, 为示例变量初始

Java类的实例化的初始化过程

A a = new A(); new 创建对象过程: 1.类加载 代码验证 2.给对象在内存(堆)中分配空间(给属性赋值): 3.属性赋默认值: byte,short.int,long ->0 float  ->0.0f double ->0.0 boolean  ->false String ->null char ->'\u0000' 4.给属性赋初始值:(用等号'=') 5.调用构造方法(方法和类名相同,没有返回类型) 6.将对象在堆区中的首地址返回给引用a /*

Java类变量和成员变量初始化过程

一.类的初始化 对于类的初始化:类的初始化一般只初始化一次,类的初始化主要是初始化静态成员变量. 类的编译决定了类的初始化过程. 编译器生成的class文件主要对定义在源文件中的类进行了如下的更改: 1)       先按照静态成员变量的定义顺序在类内部声明成员变量. 2)       再按照原java类中对成员变量的初始化顺序进行初始化. 一个java类和编译后的class对应的转换如下: 源文件: public class Person{ public static String name=

java面试扫盲:对象初始化顺序(真的未必能答对)

记录下面试里面遇到的一些java盲区,一方面扫描自己的知识盲区,一方面也可以给后面面试的朋友一些警示,以免面试的时候出现不知道的尴尬情况. 提出问题:父类静态属性,父类属性,父类构造方法,子类静态属性, 子类属性,子类构造方法的初始化顺序? 提出猜想:父类静态属性=> 父类属性=> 父类构造方法= > 子类静态属性=> 子类属性=> 子类构造方法? 方法论:实践是检验真理的唯一标准. 初步设计类的结构uml. 直接上源代码 /** * 轮子类 */ public class

java 父类子类成员变量,静态变量,构造器创建先后顺序

关于java中父类子类,成员变量,静态变量,构造器创建的先后顺序,在面试中经常会问到该类型的问题 所以用以下代码进行测试: public class Test { public static void main(String args[]) { Father f = new Son(); } } class Father { public Father() { System.out.println("Father Construct"); } static int fatherStat

java基础_对象初始化过程

1.因为new Studen()用到了Student类,所以会把它从硬盘上加载进入内存 2.如果有static静态代码块就会随着类的加载而执行,还有静态成员方法和普通方法也会随着类的加载而被加载 3.在堆中开辟空间,分配内存地址 4.在堆中建立对象特有属性(非静态成员),并同时对特有属性进行默认初始化 5.对属性进行显示初始化 比如  在类中 String name="123"; 6.执行构造代码块,对所有对象进行初始化 7.执行对应的构造函数,对对象进行初始化(调用不同的构造函数)