(注:此内容含有死亡成分,12岁以下儿童请在家长陪同下观看)
堆(Heap):对象的生存空间(又称为垃圾回收的堆)
栈(Stack):方法调用及变量的生存空间
Stack的情景:
设doStuff()方法中有go()方法,go()方法中有crazy()方法,如下过程:
Heap中的情景:
非primitive的变量只是保存对象的引用而已,而不是对象本身。不论对象是否声明或者产生,如果 局部变量是个对该对象的引用,只有变量本身会放在栈上。对象本身只会存放在堆上。
对象的 实例变量的值是存放于该对象中的。如果实例变量都是primitive主数据类型的,则Java会依据primitive主数据类型的大小为该实例变量留下空间。
如:
public class B {private int a;//根据a的数据类型为a分配空间}
若 实例变量是一个对象,Java会给引用变量留下空间,此引用变量的对象是否分配空间,则要看该实例变量是否被赋对象的值。
如下声明(在类B中):
private A a;知道引用变量被赋值一个新的A对象才会在堆上占有空间:private A a = new A();
声明对象和赋值的三大步骤:
声明引用变量、创建对象、连接对象和引用
构造函数的一项关键特征是他会在对象能够被赋值给引用之前就执行。
构造函数可以是公有、私有或不指定的。
编译器只有在完全没有构造函数时会生成默认无参构造函数。
在创建新的对象时,所有继承下来的构造函数都会执行。(子类对象创建时,
所有父类构造函数会执行)
构造函数链(Constructor Chaining)【is-a关系】
super()调用必须是构造函数的第一条语句。使用super()来调用父类构造函数。
在本类中的某个构造函数调用重载版的另一个构造函数,使用this(),与super()相同,只能是第一条语句。所以鱼与熊掌不可兼得。
this个对对象本身的引用。
生命周期
primitive主数据类型的生命周期
【Life】与【Scope】
Life:只要变量的堆栈块还存在于堆栈上,局部变量就算活着。(活到方法执行完毕为止)
Scope:局部变量的范围只限于声明它的方法之内。(当此方法调用别的方法时,局部变量还活着,状态会被保存)
对象的生命周期
引用变量的规则与primitive主数据类型相同。
只要有活着的引用,对象也就会活着。
对象杀手:
- 引用永久性的离开它的范围
- 引用被赋值到其它的对象上
- 直接将引用赋值为null