一.
具有构造函数的情况下,创建对象的时内存中的变化是怎样的。
这里我想说的是,第一句的赋值语句在内存中执行时,先是左边开始,然后是右边,最后又从右边到左边。主函数进入栈内存,同时变量也进栈。接着产生对象,对象会利用堆中的一片地址,一片地址有个头,就是首地址值。对象一旦产生,里面接着就会产生name,和age,也就是成员变量,同时两者必须初始化,对象创建完毕。以前的模式,是将地址赋给变量p2,p2指向对象,现在先不急着将地址给栈内的变量,原因在于堆内存中的运算还没结束。对象默认初始化结束后,要去找构造函数,如果对象没有调构函数的话,意味着没有创建成功。(new一个空间,然后初始化,然后构造函数失败了。对象只有初始化了才能用,对象怎么初始化,它除了一个默认的初始化以外,还要走构造函数初始化。构造函数一般可以自定义,我们必须按照我们自己的方式,对对象进行初始化,所以还没到将地址赋值给p2。) 右边开始调用构造函数,就执行到下面截图中的构造函数的语句了。这时,构造函数就进栈了,函数肯定是在栈里(函数为什么会在栈里?因为函数里面有变量,变量要进栈,那么函数就要进栈)。这就是说,对象还没将地址赋值给栈中的变量,栈中就又进了一个函数。观看下面截图中栈里的构造函数,我们不要将构造函数看的那么陌生,构造函数也是函数,只是功能特殊一些,定义函数该有的格式都是有的,有括号,有参数列表都是应该的。
将构造函数函数加载入栈中的时候,同时也将变量name和age加载进栈中,(这里的两个变量会不会有默认值?)。只要对象一调用构造函数,就往构造函数中输入“小强”和“10”两个数据,成为了构造函数参数列表中的n和a,也就是对name和age进行了赋值。→我对于函数的理解有错误。观察下面的截图,截图始终讲解的是n和a,而并非name和age。
这里重新对调用函数的这一部分进行解释。由于创建对象时,必须要通过构造函数进行初始化。先在栈中开辟空间,载入调用函数,同时将参数列表中的n和a加载入栈的调用函数内。由于在创建p2对象时,调用了特定的功能函数,且输入了具体的数据“小强”,“10”。那么就将“小强”,“10”赋值给n和a。原先在定义构造函数时,只是有形参n和a,现在调用构造函数了,且输入了具体的“小强”,“10”,那么就意味着n和a有了具体的数据,也表示对于构造函数这个盒子,我们投入了“小强”,“10”这两个参数。接着继续构造函数里面语句的执行,n要赋值给name,a要赋值给age。现在,我们从内存的角度来分析,调用函数在栈中,但是栈中既没有name,也没有age,这就需要去堆内存中,寻找name和age。这时,假设堆内存中有好几个对象,我们该去哪儿寻找name和age?由于是p2所对应的对象在调用函数,自然是去那个对象中寻找(这里面更为具体,深入地知识,将在后面讲述,这里存在一个关键字)。构造函数只负责赋值,赋值结束后,调用函数就弹栈了。
此时的对象就初始化完毕。这时,右边才算操作结束。紧跟着,右边把一个值,赋值给p2,同时有一个指向。这时,第一条语句就算结束了。
第二句p2.speak(),意味着speak进栈了,由于speak函数里没有形参,那么也就不会加载任何变量。speak函数里执行语句就是一个输出语句,将对应对象中的元素输出后,就弹栈。
二.
上面整个例子的讲解中,就是要说明对象在创建时,对象要经过两个初始化,默认初始化和构造函初始化。默认初始化,就是name=null,age=0。