《类加载与对象创建》
目录
一、过程分析
案例一
- A类
package com.hpr.test;
public class A {
static int x = 10;
int y = 10;
static {
System.out.println("静态代码块执行:x=" + (++x));
}
{
System.out.println("代码块执行:x=" + (++x) + ",y=" + (++y));
}
public A() {
System.out.println("构造方法执行...");
}
public static void aa() {
System.out.println("静态方法执行...");
}
public void cc() {
System.out.println("非静态方法执行...");
}
}
- 测试类
package com.hpr.test;
public class Test {
public static void main(String[] args) {
A a1 = new A();
System.out.println("a1:x=" + a1.x + ",y=" + a1.y);
System.out.println("------------------------------");
A a2 = new A();
System.out.println("a2:x=" + a2.x + ",y=" + a2.y);
}
}
执行结果

结果分析
- 静态代码块执行了一次;
- 代码块及构造方法每new一个对象执行一次;
- a1、a2对象共用静态变量x,单独使用非静态变量y;
- 方法调用即执行,不调用则不执行。
二、JVM运行解析
内存模型简笔图

类加载(静态变量、方法、代码块)
- JVM会先去方法区中找有没有类对应的.class存在,如果有,就直接使用;如果没有,就把对应类的.class加载到方法区;
- 将.class加载到方法区的时候,分为两部分,首先将非静态内容加载到方法区的非静态区域内;
- 再将静态内容加载到方法区的静态区域内,加载完成后,对所有的静态成员变量进行默认初始化;
- 所有静态成员变量默认初始化后,进行显示赋值,再执行静态代码块;(执行静态代码块和静态成员变量显示赋值无先后顺序,与代码顺序有关,谁在前面先执行谁)
- 如果有继承关系,加载子类的时候会先加载父类,再加载子类。
对象创建(非静态变量、方法、代码块)
-
对象创建首先会在堆内存中开辟一块空间,并分配一个地址;
-
将对象的所有非静态成员加载到开辟的空间下,并为所有非静态成员变量进行默认初始化;
-
调用构造函数进栈执行,在执行构造函数的时候,首先会执行构造函数中的隐式三步,再执行后续代码;
隐式三步:
- 执行super语句,调用父类的构造函数;
- 对所有非静态成员变量进行显示赋值;
- 执行构造代码块;(非静态成员变量显示赋值和执行构造代码块无先后顺序,由代码顺序决定,谁在前先执行谁);
-
执行完隐式三步后,再执行构造函数中的代码,代码执行完后弹栈;
-
将堆内存中开辟的空间地址赋值给一个引用对象,对象创建完成。
常见概念

三、垃圾回收机制
内存释放
- Java使用自动的处理重新分配内存的方法,即垃圾回收机制:当一个对象的引用不存在,则该对象被认为是不再需要的,它所占有的内存会被释放掉;
- Java自动回收垃圾,不需要开发人员自己控制;
- 当对象被释放时,将自动调用对象的finalize()方法;
- 如果想强制垃圾回收,可以调用System.gc()方法(非必要不建议手动调用)。
案例二
- TestGc类
package com.hpr.test;
public class TestGc {
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("回收对象:" + this);
}
public static void main(String[] args) {
//引用t指向对象
TestGc t = new TestGc();
//引用t指向新对象
t = new TestGc();
System.out.println("当前对象:" + t);
System.gc();
}
}
执行结果

四、参数传递
案例三
package com.hpr.test;
public class Transmit {
public static void valueTransmit(int xx) {
xx++;
}
public static void quoteTransmit(int[] yy) {
yy = new int[3];
}
public static void main(String[] args) {
int x = 10;
int[] y = new int[2];
valueTransmit(x);
quoteTransmit(y);
System.out.println(x); //10
System.out.println(y.length); //2
}
}
值传递

引用传递

总结
重点
- 类加载与对象创建先后顺序及主要完成事项;
- 垃圾回收机制及finalize方法;
- 值传递与引用传递。
难点
- 类加载与对象创建主要完成事项;
- 值传递与引用传递。
文章详细阐述了Java中的类加载过程,包括静态和非静态内容的加载顺序,以及对象创建的步骤,强调了静态变量和非静态变量的区别。同时,解释了垃圾回收机制,如何判断对象不再需要并释放内存,以及finalize方法的作用。此外,文章还探讨了参数传递的不同方式,值传递和引用传递的原理和区别。
680

被折叠的 条评论
为什么被折叠?



