类加载过程和对象创建的过程

一.类加载过程

在java中,类加载是指将类的相关信息加载到内存。并且只有第一次使用这个类时才会加载。
一个类的信息主要包括以下部分:

  1. 类变量(静态变量);
  2. 类初始化代码:
    – 定义静态变量时的赋值语句
    – 静态初始化代码块
  3. 类方法(静态方法);
  4. 实例变量;
  5. 实例初始化代码:
    – 定义实例变量时的赋值语句
    – 实例初始化代码块
    – 构造方法
  6. 实例方法;
  7. 父类信息引用。

类加载过程包括:

  1. 分配内存保存类的信息;
  2. 给类变量赋默认值;
  3. 加载父类;
  4. 设置父子关系;
  5. 执行类初始化代码。

内存分为栈和堆,栈存放函数的局部变量,堆存放动态分配的对象,还有一个内存区,叫方法区,存放类的信息

加载之后,java方法区就有了一份这个类的信息。
例子如下:

public class Base {
	public static int s;
	private int a;
	static {
		System.out.println("基类静态代码块,s:" + s);
		s = 1;
	}
	{
		System.out.println("基类实例代码块,a:" + a);
		a = 1;
	}

	public Base() {
		System.out.println("基类构造方法,a:" + a);
		a = 2;
	}

	protected void step() {
		System.out.println("base s:" + s + ",a:" + a);
	}

	public void action() {
		System.out.println("start");
		step();
		System.out.println("end");
	}
}

public class Child extends Base {
	public static int s;
	private int a;
	static {
		System.out.println("子类静态代码块,s:" + s);
		s = 10;
	}
	{
		System.out.println("子类实例代码块,a:" + a);
		a = 10;
	}

	public Child() {
		System.out.println("子类构造方法,a:" + a);
		a = 20;
	}

	protected void step() {
		System.out.println("child s:" + s + ",a:" + a);
	}

	public static void main(String[] args) {
		System.out.println("---- new Child()");
		Child c = new Child();
		System.out.println("\n---- c.action()");
		c.action();
		Base b = c;
		System.out.println("\n---- b.action()");
		b.action();
		System.out.println("\n---- b.s:" + b.s);
		System.out.println("\n---- c.s:" + c.s);
	}
}

内存布局如图:
在这里插入图片描述

二、对象创建的过程

在类加载之后,创建对象过程包括:

  1. 分配内存;
  2. 对所有实例变量赋默认值;
  3. 执行实例化代码。

每个对象除了保存类的实例变量之外,还保存着实际类信息的引用。
例子如下:
Child c = new Child();会将新创建的Child对象引用赋给变量c,而Base b = c;会让b也引用这个Child对象。
创建和赋值后,内存布局如下:
在这里插入图片描述
引用型变量c和b分配在栈中,他们指向相同的堆中的Child对象。Child对象存储着方法区中Child类型的地址,还有Base中的实例变量a和Child中的实例变量a。

猜你喜欢

转载自blog.csdn.net/weixin_44997483/article/details/90757242