【面向对象-06】对象初始化过程、对象调用成员过程

目录

一、对象初始化过程

1、示例代码

2、分析

3、总结

二、对象调用成员的过程

1、代码示例

2、分析

3、总结


一、对象初始化过程

1、示例代码

给出如下代码,请问一共有几条打印语句,分别是什么?

public class ObjectInitialization {
	public static void main(String[] args) {
		Person p1 =new Person("百里", 18);
		System.out.println("------------------------");
		Person p2 =new Person("慕溪", 18);
	}
}
class Person{
	//成员变量(实例变量)
	private String name;
	private int age =20;
	//静态成员变量(类变量)
	private static String country ="cn";
	//静态代码块
	static{
		System.out.println("Staic Block...country ="+country);
	}
	//构造代码块
	{
		System.out.println("Construction Block...name ="+name+", age ="+age+", country ="+country);
	}
	//构造函数
	Person(String name, int age){
		this.name =name;
		this.age =age;
		System.out.println("Construction Function...name ="+name+", age ="+age+", country ="+country);
	}
}

输出如下:

2、分析

Person p1 =new Person("百里", 18); 这句代码一执行,都做了什么事情?
1、因为 new 的时候用到了 Person 类的构造方法,所以类文件 Person.class 会被加载到内存中;
2、为静态成员变量(country)在方法区中开辟内存空间,并做如下初始化:
    |-先为静态成员 country 进行默认初始化,初始化值为 null;
    |-再为静态成员 country 进行显式初始化,初始化值为 cn;
3、执行 Person 类的静态代码块,并输出 Staic Block...country =cn;
4、OS 在堆内存中开辟空间,为 Person 类的对象分配内存地址;
5、在堆内存中建立成员变量,并进行如下初始化:
    |-先进行默认初始化:name 默认初始化为 null,age 默认初始化为0;
    |-再进行显式初始化:age 显式初始化为18;
6、构造代码块初始化,此处打印出:Construction Block...name =null, age =20, country =cn
7、构造函数初始化,name 和 age 分别显式初始化为"百里"和18, 并且打印出:Construction Function...name =百里, age =18, country =cn
8、将对象在堆内存中的首地址赋值给栈内存中的 Person 类的引用变量p1。

PS:为什么执行 Person p2 =new Person("慕溪", 18); 这句代码的时候没有输出 Staic Block...country =cn;

3、总结

在调用一个类的构造方法进行对象的创建的时候,进行的动作如下:
1.为类中静态成员变量(类变量)初始化,先默认初始化,再显式初始化;
2.执行类中的静态代码块为类初始化;
PS:前两步是可选的,只有当类中存在静态成员变量和静态代码块时,才对应执行前面两步,两者都是当类加载到内存时执行,并且仅仅执行一次!
3.为实例变量进行初始化,先默认初始化,再显式初始化;
4.执行类中构造代码块为该对象进行公共初始化;
5.执行构造函数为该对象进行特定初始化。

二、对象调用成员的过程

1、代码示例

class Person{
	private String name;
	private int age =20;
	private static String country="cn";
	
	Person(String name, int age){
		this.name =name;
		this.age =age;
	}
	
	public void speak(){
		System.out.println(this.name +"..."+ this.age);
	}
	
	public void setName(String name){
		this.name =name;
	}
	
	public static void showCountry(){
		System.out.println("country ="+ country);
		method();
	}
	
	public static void method(){
		System.out.println("static method is running");
	}
}

class Test{
	public static void main(String[] args) {
		Person p =new Person("Benjamin", 28);
		p.setName("ZXM");
		Person.showCountry();
	}
}

2、分析

main 方法执行每一句代码,内存变化过程如下:


1、对象初始化过程在前面,并且在栈内存中,为 main 方法开辟了方法中局部变量的内存空间,此时 Person 类引用变量 p 指向堆内存中的 Person 类对象,name 值为 Benjamin,age 值为20;
2、执行 p.setName("ZXM"):
         首先 OS 在栈内存中为 setName() 方法开辟了局部变量的内存空间,并且形参 name 接受 main 方法中传入的实参,初始化为ZXM;由于 setName() 为非静态方法,并且调用了该对象的另一个非静态成员,所以这个 name 成员所属的对象就是 this;这个 this 就是在主方法中调用 setName() 方法的对象p;因此 setName() 中的 this 指向堆内存中的那个对象,p.setName(“ZXM”) 相当于将p的值赋值给了 this,每一个非静态方法中都有一个 this 变量;执行完之后,栈内存的 setName() 中对应的临时变量 name 和引用变量 this 全部释放。
3、执行到 Person.showCountry():
         这是个静态方法,在栈内存中开辟了临时变量的内存空间,注意:静态方法中是没有 this 的! 此时调用的静态变量 country 并没有经过堆内存,而是经过方法区中的 country,值为cn。
4、静态方法 showCountry() 中又调用了另一个静态方法 method(),此时在栈内存中也为 method() 开辟了一个局部变量对应的内存空间。

public static void showCountry(){
	System.out.println("country ="+ country);
	method();
}

PS:如上代码 showCountry() 中调用了method();这个method() 前面有省略的东西么?一定有!因为只要是方法执行了,一定是被调用了,必须先调用,后执行。
静态方法之间相互访问,如果写成直接访问,那省略的一定是“类名.”,如下:

public static void showCountry(){
	System.out.println("country ="+ country);
	Person.method();
}

3、总结

1、非静态成员方法直接访问其他非静态成员,省略的是"this.";
2、静态成员方法直接访问其他的静态成员,省略的是"类名.";
3、代码和代码中使用到的数据是相对独立的内存区域。

另:JAVA基础篇006-什么是类变量、实例变量、以及区别

每天记录一个小知识,分享是一种快乐,点赞是一种美德!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值