小谈Java中类加载以及对象初始化的过程

探讨Java中类加载到完成一个对象创建的过程

Java作为面向对象的一门语言,在程序中最重要的也是最基础的就是通过类创建对象,在本文中我简单聊一聊对于这个过程我个人的理解。有不足之处还请多多指正。

一个Java类中有什么?

这里写图片描述

那么当我们创建一个对象时执行了哪些操作呢?

类加载以及对象创建及其初始化

类加载:发生在类第一次被虚拟机调用,类会被虚拟机加载一次,一般来说,也只被加载一次

类加载执行的操作:

1.初始化类变量
2.分配类方法的函数入口
3.执行静态块
对象创建以及对象初始化晚于类加载的时间

因为静态部分是依赖于类的,不依赖于对象存在的,所以静态部分的加载先于类的加载。

对象创建及实例化的步骤

1.初始化实例变量
2.为实例方法分配函数入口(在第一个对象创建时分配)
3.执行对象块(对象块是每创建一个对象,执行一次)
4.执行构造函数(注意super()),以及剩余部分

执行完上述步骤后才算是完成了一次对象的创建。

具体解释

public class Test1{
	//1.初始化类变量
	static String staticVar = "我是静态变量";
	
	//2.分配类方法的函数入口
	public static void  statFunc(){
		System.out.println("我是静态方法,我被执行啦!");
	}
	//3.执行静态块
	static {
		//只执行一次,多数用于在程序启动的时候,初始化一些静态资源,如图片,音乐等等
	}
	
	//4.执行main()方法
	public static void main(String args[]){
	
	}
}

小小总结一下:

因为静态部分是依赖于类,而不是依赖于对象存在的,所以静态部分的加载优先于对象存在。

当找到main方法后,因为main方法虽然是一个特殊的静态方法,但是还是静态方法,此时JVM会加载main方法所在的类,试图找到类中其他静态部分,即首先会找main方法所在的类。

在这里插入图片描述

test2:

public calss Test2{
	//1.初始化实例变量,注意:初始化实例变量  !=  给实例变量赋值
	String name="实例变量";
	
	//2.为实例方法分配函数入口,注意第一个对象创建的时候分配入口地址
	public void init(){
		System.out.print("实例方法被调用");
	}
	
	//3.执行对象块
	{
		//每创建一个对象,都会执行一次对象块
		//可以在创建每一个对象的时候,给对象设置状态,属性等等
	}
	//4.执行构造函数(super();剩余语句才是第四部分执行的)
	public static void main(String args[]){
	     Test2 t2=new Test2();
	     ....
	}
}

关于上面的第四点:

4.执行构造函数(super();剩余语句才是第四部分执行的)

注意:构造方法的调用:

        以派生的顺序调用,从父类到子类

可以理解为:(灵魂画手…希望读者能看明白)
在这里插入图片描述

看看一些经典例子(太经典了,侵删

package test;

class A {
	public A() {
		System.out.println("A的构造方法");
	}

	public int j = print();

	public static int print() {
		System.out.println("A print");
		return 521;
	}
}

public class Test extends A {
	public Test() {
		System.out.println("Test的构造方法");
	}

	public static int k = print();

	public static int print() {
		System.out.println("Test print");
		return 522;
	}

	public static void main(String[] args) {
		System.out.println("main start");
		Test test = new Test();
	}
}

输出:(可以自己更改程序多运行几次熟悉熟悉)

在这里插入图片描述

另一个经典例子:

public class Text {
    public static int k = 0;
    public static Text t1 = new Text("t1");
    public static Text t2 = new Text("t2");
    public static int i = print("i");
    public static int n = 99;
    public int j = print("j");

    {
        print("构造块");
    }
    static {
        print("静态块");
    }

    public Text(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String args[]) {
        Text t = new Text("init");
    }
}

输出:
在这里插入图片描述

这里补充下知识点:

super关键字:

1. 调用构造方法

    类似this(),super()必须是子类构造函数第一个执行的语句,如果super()没用到,每个父类的默认构造或无参构造函数将被执行

2. 调用被隐藏变量及方法

    可通过super关键字调用被隐藏的父类中的变量及方法

this关键字:

this在方法用,指向当前对象,属于调用这个方法的当前对象

用法

  1. this.变量/方法 ---->指代的是通过当前对象调用的变量/方法(不能用于静态方法中)
  2. this(【参数】) ------>一般用于构造器中,调用当前类的其他构造方法(必须是构造方法中的第一条语句)

参考链接

  1. https://www.cnblogs.com/greatfish/p/5771548.html
  2. https://blog.csdn.net/ln152315/article/details/79223441
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值