在Java中,程序员会在乎内存中的两块空间。 堆(heap)和栈(stack)。
当java虚拟机启动时, 它会从底层的操作系统取得一块内存, 并且以此块内存来执行java程序。
在Java中, 实例变量是声明在类中而不是方法中的变量,实例变量存在于所属的对象中, 即实例变量会随着对象一起位于堆上。
Java中的局部变量以及平时所说的形参(方法的参数)都是被声明在方法中,局部变量会放在栈上。随着方法调用产生,当方法执行完毕局部变量的使命也就完成,
会被弹出栈空间而消失。Java中对象引用也可以看成是一种局部变量, 也是位于栈(stack)上的。
有一点始终要牢记, 那就是java中对象是会放在堆上的,即堆上会放着 new() 出来的对象。
然后关于java中变量的生命周期 :
1. 局部变量(local varible)只会存活在生命变量的方法中, 方法执行结束时局部变量会被弹出栈进而消失。
2. 实例变量,实例变量是随着对象一起存在于堆(heap)上的, 所以实例变量的生命周期与对象相同, 如果对象还活着那么实例变量也仍然存活。
3. 对象: 位于堆上,当没有引用指向对象时, 一段时间以后对象就会被垃圾收集器(GB)给清理掉了,位于对象上的实例变量也就消失了。
然后我们来回顾下对象创建的三个步骤 : 声明、创建、赋值。 例如 :Duck myDuck = new Duck(); 执行过程可以这样看 :
如果我们注意到第二步,new Duck() 看起来像是不是在调用Duck()的方法,其实不然, 我们此处通过new这个关键字调用了Duck()的构造函数。
构造函数并不是方法, 它是程序中带有new的时候会执行的代码。它能够在对象赋值给引用之前首先执行。
构造函数(constructor)是你初始化对象时会执行的程序代码。 也就是创建一个对象时会被执行。 当你自己没有写, 编译器在编译时会帮你加上一个没有参数的构造函数。
但是编译器一定会帮你写出无参的构造函数吗? The Answer is : NO !!!
编译器只会在你完全没有编写构造函数的时候帮你加上一个构造函数, 但是如果你已经写了一个有参数的构造函数, 而且再需要一个无参的构造函数,
你不能指望编译器会帮你加上, 你必须自己动手实现。
然后来看看构造函数的执行: 参考 http://www.cnblogs.com/beyond-Acm/p/4077320.html
有两条规则 :a. 子类的构造方法首先必须调用父类的构造方法。
(可能刚开始学会觉得奇怪,为什么一定要首先去调用父类的构造方法呢? 其实换个思路可能理解起来就很简单了, 你可以吧父类想象成子类的父母,
怎么可能父母还没造出来先把孩子造出来了呢?更何况孩子还需要从父母那里继承一些东西)
b. 如果没有显示指定,子类的构造方法会默认的调用父类中的无参构造方法。这会连锁反应到object这个类终止。 这个过程被称为 constructor chaining 。
c. 调用父类构造函数的唯一方法是 super()。
总结下编译器涉及构造函数的两种方式 :
1. 如果你没有编写构造函数, 那么编译器在编译时会帮你在类中加入如下代码 :
public className () {
super();
}
2. 如果你自己编写了构造函数但是没有调用super(), 那么编译器会在你每个重载的构造函数之前都加上这种调用 : super(); 编译器帮忙加的一定是没有参数的构造函数
假如父类有多个构造函数, 那么也只有无参的构造函数会被调用到。 此时如果父类里没有无参的构造函数则会报错。