Java之对象构造过程
先来运行一段代码
class A {
public A() {
init();
}
public void init() {
}
public static void main(String[] args) {
B b = new B();
System.out.println("终于i的值为:" + b.i + ",j的值为:" + b.j);
}
}
class B extends A {
int i;
int j = 999;
public void init() {
System.out.println("此时A的构造方法正在调用此方法:i的值为:" + i + ",j的值为:" + j);
i = 888;
j = 111;
}
}
看看打印什么
此时A的构造方法正在调用此方法:i的值为:0,j的值为:0
终于i的值为:888,j的值为:999
假设感到非常吃惊,那么你对Java对象的构造过程还不熟悉。那么认真阅读本文将对你有非常大帮助。
先写个案例代码
public class Super {
static long time = 10;
static Object obj = new Object();
int width = 100;
static {
time = 11;
}
{
width = 110;
}
public Super() {
width = 120;
}
public static void main(String[] args) {
Child child = new Child();
System.out.println("Super.time:"+Super.time);
System.out.println("Super.obj:"+Super.obj);
System.out.println("child.width:"+child.width);
System.out.println("Child.age:"+Child.age);
System.out.println("Child.str:"+Child.str);
System.out.println("child.height:"+child.height);
}
}
class Child extends Super {
static int age = 20;
static String str = "str";
double height = 200;
static {
age = 22;
}
{
height = 210;
}
public Child() {
height = 220;
}
}
打印
Super.time:11
Super.obj:java.lang.Object@659e0bfd
child.width:120
Child.age:22
Child.str:str
child.height:220.0
Java中一个对象的构造过程
1.用类载入器载入父类。按父类静态变量定义的顺序的为父类全部静态变量分配空间,并赋予父类静态变量默认值
public class Super {
static long time=10;//此时time=0
static Object obj=new Object();//此时obj=null
2.用类载入器载入自己,按自己静态变量定义的顺序的为自己全部静态变量分配空间,并赋予自己静态变量默认值
class Child extends Super{
static int age=20;//此时age=0
static String str="str";//此时str=null
3.按父类静态变量定义的顺序的为父类全部静态变量赋上定义的值
public class Super {
static long time=10;//此时time=10
static Object obj=new Object();//此时obj=new Object()
4.运行父类静态代码块
public class Super {
static long time=10;
static Object obj=new Object();
int width=100;
static{
time=11;//静态代码块运行了。这个时候time=11
}
5.按自己静态变量定义的顺序的为自己全部静态变量赋上定义的值
class Child extends Super{
static int age=20;//此时age=20
static String str="str";//此时str="str"
6.运行自己静态代码块
class Child extends Super{
static int age=20;
static String str="str";
double height=200;
static{
age=22;//此时age=22
}
7.为父类实例变量分配空间。并赋予默认值
public class Super {
static long time=10;
static Object obj=new Object();
int width=100;//此时width=0
8.为自己实例变量分配空间。并赋予默认值
class Child extends Super{
static int age=20;
static String str="str";
double height=200;//此时height=0.0
9.按父类实例变量定义的顺序的为父类全部实例变量赋上定义的值
public class Super {
static long time=10;
static Object obj=new Object();
int width=100;//此时width=100
10.运行父类的构造代码块
public class Super {
static long time=10;
static Object obj=new Object();
int width=100;
static{
time=11;
}
{
width=110;//此时width=110
}
11.运行父类的构造方法
public class Super {
static long time=10;
static Object obj=new Object();
int width=100;
static{
time=11;
}
{
width=110;
}
public Super() {
width=120;//此时width=120
}
12.按自己实例变量定义的顺序的为自己全部实例变量赋上定义的值
class Child extends Super{
static int age=20;
static String str="str";
double height=200;//此时height=200.0
13.运行自己的构造代码块
class Child extends Super{
static int age=20;
static String str="str";
double height=200;
static{
age=22;
}
{
height=210;//此时height=210.0
}
14.运行自己的构造方法
class Child extends Super{
static int age=20;
static String str="str";
double height=200;
static{
age=22;
}
{
height=210;
}
public Child() {
height=220;//此时height=220.0
}
对象构造完毕!
注意
1-6属于初始化静态部分,7-14属于初始化实例部分
假设一个类的静态部分已经初始化了(已经被类载入器载入了)。就不会再反复初始化静态部分,静态部分的初始化仅仅会在类载入器载入一个类的时候初始化一次
父类假设还有父类就也按照此顺序先初始化父类的父类,直到Object为止
假设运行步骤3,5,9,12赋值操作时,假设发现所赋的值的类还没有初始化,则会先初始化那个引用的类,假设引用的类还有引用的类则也依照此顺序先初始化引用类的引用类。直到所有被引用的类所有被初始化完成为止
比如:
我们在A类中定义一个B类的引用。
public class Super {
public static void main(String[] args) {
new A();new B();
}
}
class A{
static B b=new B();//这句代码会导致B类会比A类先初始化完毕,也就是说B的静态属性会先赋值,静态代码块会先运行。
static {
System.out.println("AA");
}
}
class B{
static {
System.out.println("BB");
}
}
打印:
BB
AA
仅仅定义一个类的引用,而没有赋值,那么不会触发一个类初始化
public class Super {
public static void main(String[] args) {
new A();
}
}
class A{
static B b;
static {
System.out.println("AA");
}
}
class B{
static {
System.out.println("BB");
}
}
打印:
AA
仅仅有触发了主动使用才会导致所引用的类被初始化.
关于一个人在什么情况才算是主动使用请查看我的还有一篇文章:
http://blog.csdn.net/u012643122/article/details/46522345
假设一个类A的所引用的类B里又引用了类A,也就是递归引用的情况,那么会实施java消除递归机制
如
public class Super {
public static void main(String[] args) {
new A();
}
}
class A{
static B b=new B();
static {
System.out.println("AA");
}
}
class B{
static A a=new A();
static {
System.out.println("BB");
}
}
打印
BB
AA
初始化引用的类时就像走一条路,java避免递归的机制就是不走之前已经走过的地方.
假设在运行3、5、9、12时。发现变量仅仅定义了引用而没有赋值操作,那么该变量将保持默认值
如:
static long time;//保持之前所赋的默认值0
Child child;//保持之前所赋的默认值null
特殊情况可省略的步骤
假设一个类没有父类(如Object类),则它的初始化顺序能够简化成2、5、6、8、12、13、14。
假设这个类已经被类载入器载入过了,也就是该类的静态部分已经初始化过了,那么1、2、3、4、5、6都不会运行,总的顺序能够简化为7、8、9、10、11、12、13、14。
假设这个类没有被类载入器载入,但它的父类已经被类载入器载入过了。那么总的顺序能够简化为2、5、6、7、8、9、10、11、12、13、14。
转载请标明原地址。请尊重原创,谢谢!
Java之对象构造过程的更多相关文章
- Java内存结构、类的初始化、及对象构造过程
概述 网上关于该题目的文章已经很多,我觉得把它们几个关联起来讲可能更好理解一下.与其它语言一样,它在执行我们写的程序前要先分配内存空间,以便于存放代码.数据:程序的执行过程其实依然是代码的执行及数据的 ...
- Java的对象初始化过程
成员变量(字段)初始化顺序 在一个类里初始化的顺序是由成员变量在类里面的定义的顺序来决定的.即使成员变量大量散布于类的各个方法定义的中间,那些成员变量仍会在调用任何方法之前得以初始化,甚至在构造函数调 ...
- Java中对象构造
构造函数 作用:在构造对象的同时初始化对象.java强制要求对象 诞生同时被初始化,保证数据安全. 调用过程和机制:①申请内存,②执行构造函数的函数体,③返回对象的引用. 特点:与类同名,无返回类型, ...
- Java基础—对象构造
1.重载 有些类有多个构造器.例如,可以如下构造一个空的StringBuilder对象: StringBuilder message = new StringBuilder(); 或者,可以指定一个初 ...
- Java中对象创建过程
本文介绍的对象创建过程仅限于普通Java对象,不包括数组和Class对象. 1.类加载检查 虚拟机遇到一条new指令时,首先去检查该指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用 ...
- 转:java实例化对象的过程
学习JAVA这门面向对象的语言,实质就是不断地创建类,并把类实例化为对象并调用方法.对于初学JAVA的人总搞清楚对象是如何实例化的,假如类之间存在继承关系,那就更糊涂了.下面我们通过两个例题来说明对象 ...
- java实例化对象的过程
总结以上内容,可以得到对象初始化过程: 1. 如果存在继承关系,就先父类后子类: 2 .如果在类内有静态变量和静态块,就先静态后非静态,最后才是构造函数: 3 .继承关系中,必须要父类初始化完成 ...
- Java中对象初始化过程
Java为对象初始化提供了多种选项. 当new一个对象的时候,对象初始化开始: 1.首先,JVM加载类(只加载一次,所以,即使多次new对象,下面的代码也只会在第一次new的时候执行一次),此时, 静 ...
- .ctor,.cctor 以及 对象的构造过程
摘要: .ctor,.cctor 以及 对象的构造过程.ctor:简述:构造函数,在类被实例化时,它会被自动调用.当C#的类被编译后,在IL代码中会出现一个名为.ctor的方法,它就是我们的构造函数, ...
随机推荐
- CSS实现背景透明,文字不透明
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- php <a href></a>链接地址中是php变量,链接文本也是php变量的代码处理方法
1.所用php变量名为$recent_tests,是一个二维数组,示例如下: $recent_tests[0]["test_url"] = www.baidu.com $recen ...
- HDU 5150 Sum Sum Sum 素数
Sum Sum Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- java中HashMap在多线程环境下引起CPU100%的问题解决
最近项目中出现了Tomcat占用CPU100%的情况,原以为是代码中出现死循环,后台使用jstack做了dump,发现是系统中不合理使用HashMap导致出现了死循环(注意不是死锁). 产生这个死循环 ...
- vultr vs digitalocean vs linode
vultr官方网站:www.vultr.comdigitalocean官方网站:www.digitalocean.comlinode官方网站:www.linode.com 一般来说我们买VPS的时候都 ...
- PyQt5 布局
import sys from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QVBoxLayout, QHBoxLayout, QPus ...
- .NET泛型02,泛型的使用
在" .NET泛型01,为什么需要泛型,泛型基本语法"中,了解了泛型的基本概念,本篇偏重于泛型的使用.主要包括: ■ 泛型方法重载需要注意的问题■ 泛型的类型推断■ 泛型方法也可以 ...
- MVC自定义路由01-为什么需要自定义路由
本篇体验自定义路由以及了解为什么需要自定义路由. 准备 □ View Models using System.Collections.Generic; namespace MvcApplicati ...
- redis java操作
Redis Java连接操作 连接到Redis服务器 import redis.clients.jedis.Jedis; public class RedisJava { public static ...
- java内存溢出示例(堆溢出、栈溢出)
堆溢出: /** * @author LXA * 堆溢出 */ public class Heap { public static void main(String[] args) { ArrayLi ...