许多的人并不是很了解一个对象的创建过程是这样的,甚至很多自诩写过的代码超过万行的人也不清楚,笔者也就是这类人,吃过亏后痛定思痛,重新的学习和研究了整个过程。
当系统加载类和创建该类的是实例时,系统自动的为成员变量分配内存空间,并在分配内存空间后自动为成员变量指定初始值。例子:
创建类 test
public classtest {
private static int j = getNumber();
public int x = getX() ;
private int a = getA();
public void info(){
System.out.println("这里执行的是test的info()");
}
protected void infoTest(){
System.out.println("test保护性成员的测试");
}
private static int getNumber(){
System.out.println("******getNumber()函数");
return 1;
}
private int getX(){
System.out.println("*******getX()的方法");
return 3;
}
private int getA(){
System.out.println("*******getA()的方法");
return 4;
}
}
创建子类 Vtest
public classVtest extends test{
private static int a = getA() ;
private int b = getB();
private int x = getX();
public Vtest(){
// System.out.println("Vtest()的构造函数");
}
private int getB(){
System.out.println("——————————getB()函数被调用了");
return 3;
}
private static int getA()
{
System.out.println("————————————t中getA()被调用了");
return 4;
}
private int getX(){
System.out.println("————————————t中getX()被调用了");
return 5;
}
public void info(){
super.info();
System.out.println("这里执行的是Vtest的info()函数");
}
public void infoTest(){
super.infoTest();
System.out.println("这里执行的是Vtest的infoTest()函数");
}
public void infoTest(int j){
System.out.println("这里执行的是Vtest的infoTest(intj)函数");
}
public static void main(String[] args){
// TODO Auto-generated methodstub
new Vtest();
System.out.println("***************************");
new Vtest();
System.out.println("***************************");
new test();
}
}
运行的结果:
******getNumber()函数
————————————t中getA()被调用了
*******getX()的方法
*******getA()的方法
——————————getB()函数被调用了
————————————t中getX()被调用了
***************************
*******getX()的方法
*******getA()的方法
——————————getB()函数被调用了
————————————t中getX()被调用了
***************************
*******getX()的方法
*******getA()的方法
分析两个类和最终的运行结果我们可以看出:
当程序执行 new Vtest()时,由于是第一次使用Vtest类,于是系统先加载这个类,并且初始化这个类。这个阶段姑且叫做类的准备阶段,在这个阶段系统会为该类的成员变量或者成员常量分配内存空间并指定默认值。由于static修饰的表示该类的本身,因此在加载类时它们首先被加载并且分配内存的空间。当加载完成类后,接着就是创建对象。
再次执行new Vtest(),由于类已经加载完成,于是不需要再一次加载,这里就直接的创建对象,这就是为什么都是new Vtest()但是两次执行的结果不一样的原因。
于是读者也许又有疑问:new test第一次加载时为什么没有先加载static 修饰的呢,这是因为 mian()在Vtest()里面会首先的加载。
我们经常这样写 Vtest t =new Vtest();其实这句话会执行两个过程,第一个过程创建对象Vtest()在堆内存,其次产生 Vtest类型的变量 t在栈内存,t保存的是Vtest对象在堆内存的地址而不是整个该对象的复制品。这是读者又有疑问,既然是已经通过new Vtest()创建了对象,为什么还需要声明一个Vtest t的变量,因为操作在堆内存的对象只能通过这个 t。如果我们不需要这个对象,只需要切断 t与这个对象的联系即是 t = null这时java的内存回收机制就会来回收这块内存了。