您的位置:首页 > 职场人生

黑马程序员——面向对象9:对象的初始化&方法的调用

2014-10-07 23:10 274 查看
------- android培训java培训、期待与您交流! ----------

这一篇我们来详细描述一下,创建一个对象和对象调用方法时,在内存中都发生了什么,也算是对之前学习的内容的一个总结。
代码1:
class Person
{
private String name;
private int age;
private static String country = "CN";
{
System.out.println("name = "+this.name+",age = "+this.age);
}

Person(String name, int age)
{
this.name  = name;
this.age = age;
}

public void setName(String name)
{
this.name = name;
}
public void speak()
{
System.out.println("name="+this.name+",age="+this.age);
}
public static void showCountry()
{
System.out.println("country = "+country);
}
}<strong style="text-decoration: underline;">
</strong>class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person("Tom", 33);
p.setName(“Jack”);
}
}
1. 对象的初始化过程

当主函数运行到“Person p = new Person()”语句时,
第一步:在栈内存中为主函数开辟一块空间,并先执行赋值符左侧的语句,在栈内存中创建一个Person类类型变量p;
第二步:在继续执行右侧的语句之前,将Person类加载进内存,更具体说,就是当执行“new Person()”时,虚拟机将“Person.class”(字节码)文件加载进内存;
第三步,加载Person类的同时,在方法区中为该类开辟一块空间(所谓开辟,其实就是将这片内存区域清零,也就是默认初始化,下同),与此同时在此创建这个类的所有静态成员和方法(注意,静态方法和非静态方法是分在两个空间存储的),然后对静态成员变量(该例中为country)进行默认初始化(引用数据类型变量赋null,boolean型变量赋false,其他基本数据类型变量赋0,下同),最后进行显示初始化;
第四步:如果有的话执行静态代码块;
第五步:在堆内存为Person对象开辟了一块空间,并为这个空间分配一个地址值,接着在此创建该对象所有的非静态成员变量(该例中为name和age)并进行默认初始化,然后进行显示初始化;
第六步:如果有的话执行对象的构造代码块;
第七步:执行相对应的构造函数;
第八步:最后将上述内存的地址值赋给栈内存中的变量p,p就指向了堆内存中的Person对象。
2. 方法的调用
当主函数运行“p.setName(“Jack”)”语句时,在栈内存为setName方法开辟一块空间,并在其内部创建局部变量name,而且这块内存空间一开辟就存在了对本类对象的引用——this。实际上这个this的值就是对象在堆内存中的地址值,那么this也就指向了堆内存中调用setName方法的本类对象。在调用setName方法的同时将字符串“Jack”作为实际参数传入setName方法中,这个值接着赋给了方法中的局部变量name,然后通过赋值语句将“Jack”赋给了堆内存中Person对象(this关键字的作用)的成员变量——name。
以上就是非静态方法的调用过程在内存中的体现。如果是调用静态方法,比如showCountry方法,那么与调用非静态方法的相同点是:都要在栈内存为方法开辟一块空间;区别在于:因为没有对象产生,所以不涉及堆内存,也不需要this关键字的指向作用;只是栈内存与方法区中的变量之间的互相访问。

小知识点1:
大家都知道静态方法只能调用静态方法,比如下述代码,
代码2:
class Demo
{
public static void method()
{
System.out.println(“method run”);
}
public static void function()
{
System.out.println(“function run”);
method();
}
}
上述代码中,function方法内部调用了method方法,这就和非静态方法互相调用相同时放方法名前面省略了this一样,静态方法相互调用时方法名前省略了类名,所以完整写法是“Person.method()”。这同样也适用于静态成员变量。实际上,大家要记住,所有方法(无论是否静态)的执行都是需要调用者,静态方法的调用者是类,非静态方法是对象,主函数是虚拟机。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐