<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="java"><span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif; font-size: 12px;">栈与堆:生存空间</span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);"> </span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);">在Java中,程序员会在乎内存中的两种区域:对象的生存堆(heap)和方法调用及变量的生存空间(stack)。</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="java"><span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif; font-size: 12px;">栈与堆:生存空间</span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);"> </span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);">在Java中,程序员会在乎内存中的两种区域:对象的生存堆(heap)和方法调用及变量的生存空间(stack)。</span>
栈存放着方法调用和局部变量。当你调用一个方法时,该方法会放在调用栈的栈顶,实际被堆上栈的是堆栈块,它带有方法的状态,包括执行到哪一行程序以及所有的局部变量的值。栈顶上的方法是目前正在执行的方法(不止一个)。方法会一直待在这里直到执行完毕。
另外需要记住的是,如果局部变量是个对该对象的引用,只有变量本身会放在栈上。对象只会存在堆上。
对象的实例变量的值是存放于该对象中的,因此也在堆上。如果实例变量是primitive主数据类型,则会在相应区域留下空间(int 4个字节,long为8个字节);如果是引用变量,则只会是变量的空间,直到引用变量被赋值一个新的对象,才会在堆上新生成一个对象。
新对象创建的3个步骤:
Duck my Duck = new Duck();
1) 声明引用变量:
Duck myDuck = new Duck();
2) 创建对象
Duck my Duck = new Duck();
3)连接对象与引用
Duck myDuck = new Duck();
Duck myDuck = new Duck();
Duck() 可以理解为类Duck的构造方法。
那么构造方法可以做些什么?
构造方法
在创建新对象时,所有继承下来的构造方法都会被执行。因为子类可能会根据父类的状态来继承方法(也就是父类的实例变量)。完整的对象需要也是完整的父类核心,所以也就是为什么父类构造方法必须执行的原因。就算父类上有些变量是子类不会用到的,但Hippo可能会用到某些继承下来的方法必须读取父类的实例变量。
例如:
class Animal{
public Animal(){
System.out.println("Making an Animal");
}
class Hippo extends Animal{
public Hippo(){
System.out.println("Making an Animal");
}
public class TestHippo {
public static void main (String[] args){
System.out.println("Starting...");
Hippo h = new Hippo();
}
}
结果是
class Animal{
public Animal(){
System.out.println("Making an Animal");
}
class Hippo extends Animal{
public Hippo(){
System.out.println("Making an Animal");
}
public class TestHippo {
public static void main (String[] args){
System.out.println("Starting...");
Hippo h = new Hippo();
}
}
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="java">Starting..
Making a Hippo
Making an Animal
1)某个程序执行new Hippo()的动作,Hippo()的构造方法进入堆栈最上方的堆栈块。
2)Hippo()调用父类的构造方法导致Animal()的构造函数进入栈顶。
3)Animal()调用父类的构造方法导致Object()的构造方法进入栈顶。
4)Object()执行完毕,它的堆栈块被弹出,接着继续执行Animal()的构造方法。
也就是说,如果我们没有调用super(),编译器会帮我们加上super()的调用。
1) 如果没有编写构造方法
public ClassName(){
super();
}
2)有构造方法但没有调用super(),编译器会帮你对每个重载版本的构造方法加上无参数的调用。
super();
有参数的构造方法
添加super(var1)来调用父类的构造方法,以完成父类私有变量的赋值。
用this() 可以调用重载版的另一个构造方法。但是this()只能用在构造方法中,且它必须是第一行语句,super()与this()不能兼得。