Java中对象初始化的理解

1.类:数据域+构造方法+方法。数据域:声明并初始化变量。构造方法:主要初始化,也可完成其他行为动作。方法:定义对象或类动作。

2.引用变量的声明类型决定了编译时匹配那个方法,编译器会在编译时,根据参数类型、参数个数和参数顺序找到匹配的方法。一个方法可能在子类中都被实现。JVM在运行时动态绑定方法的实现,是根据变量的实际类型决定的。Father a =  new Son();

3.构造方法:与所在类同名,无返回类型,在构建一个对象时使用new操作符调用。不可继承,只是调用,动态绑定。

4.static:共享区,静态区。在编译中就分配内存。static修饰的变量和方法,不属于某个特定的对象,可以类.静态方法调用。在static方法中调用非静态方法,也就是类.非静态方法调用,没有实例化,而对于非静态方法调用必须实例化,这将导致this无法引用有效的对象,因而造成编译错误。生命周期整个类,作用范围分局部和全部之分。静态方法,为同类中所有对象共享,不依附于某个对象。创建多个对象,static依然是创建一个,共享一个内存空间,,初始化只一次。

http://www.chinastor.org/upload/2013-12/13121914502374.pdf   p114  p157

在许多传统语言里,程序都是作为启动过程的一部分一次性载入的。随后进行的是初始化,再是正式执行程
序。在这些语言中,必须对初始化过程进行慎重的控制,保证 static 数据的初始化不会带来麻烦。比如在一
个static 数据获得初始化之前,就有另一个 static 数据希望它是一个有效值,那么在 C++中就会造成问
题。 
Java 则没有这样的问题,因为它采用了不同的装载方法。由于 Java 中的一切东西都是对象,所以许多活动
变得更加简单,这个问题便是其中的一例。正如下一章会讲到的那样,每个对象的代码都存在于独立的文件
中。除非真的需要代码,否则那个文件是不会载入的。通常,我们可认为除非那个类的一个对象构造完毕,
否则代码不会真的载入。由于 static 方法存在一些细微的歧义,所以也能认为“类代码在首次使用的时候载
入”。 
首次使用的地方也是static 初始化发生的地方。装载的时候,所有static 对象和 static 代码块都会按照本
来的顺序初始化(亦即它们在类定义代码里写入的顺序)。当然,static 数据只会初始化一次。 


5.New对象加载顺序:静态区,数据域中变量声明分配栈(赋予默认值),构造函数,数据域变量绑定对象(对象都在堆中),按次序调用方法。

6.系统在类初始化阶段执行静态代码块、普通代码块、构造函数初始化时,不仅会执行本例的,而且会一直上溯到java.lang.Object类,先执行Object,然后执行父类...一直到该类的初始化过程。其中在你创建多个对象时,静态代码块只执行一次。


========code1=======

public class Test2{
		public static void main(String[] args) {
			A a=new B(); 
		}
	}
class A{
	A(){test();}
	public void test(){
	}
}
class B extends A{
	String s = "ZJG";
	B(){super();}
	public void test(){
		System.out.println(s);
	}
}

================output1==================

null

=====code2======

public class Test2{
    public static void main(String[] args){
        Son d = new Son();
        System.out.println( d.a );
    }
    Test2() {
        preProcess();
    }
     void preProcess() {}
}

class Son extends Test2
{
    //public static int a = 45;
    public  int a = 45;
    void preProcess(){
        System.out.println(a);
    }
}

================output2==================

0

45

=====code3======

public class Test2{
    public static void main(String[] args){
        Son d = new Son();
        System.out.println( d.a );
    }
    Test2() {
        preProcess();
    }
     void preProcess() {}
}

class Son extends Test2
{
    public static int a = 45;
    //public  int a = 45;
    void preProcess(){
        a = 4;
        System.out.println(a);
    }
}

================output3==================

4

4

=====code4======

class Root
{
	{
		System.out.println("Root");
	}
	static 
	{
		System.out.println("Root static");
	}
	public Root()
	{
		System.out.println("Root constructed function");
	}
}
class Mid extends Root
{
	{
		System.out.println("Mid");
	}
	static 
	{
		System.out.println("Mid static");
	}	
	public Mid()
	{
		System.out.println("Mid constructed function");
	}
}
public class Last extends Mid
{
	{
		System.out.println("Last");
	}
	static 
	{
		System.out.println("Last static");
	}	
	public Last()
	{
		System.out.println("Last constructed function");
	}
	public static void main(String[] args) 
	{
		new Mid();
		System.out.println("Hello World!");
		new Mid();	
	}
}

================output4==================

 

=====转自http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html

1  无继承情况下的Java初始化顺序:
class Sample
{
      Sample(String s)
      {
            System.out.println(s);
      }
      Sample()
      {
            System.out.println("Sample默认构造函数被调用");
      }
}
class Test{
      static Sample sam=new Sample("静态成员sam初始化");
      Sample sam1=new Sample("sam1成员初始化");
      static{
            System.out.println("static块执行");
            if(sam==null)System.out.println("sam is null");
            sam=new Sample("静态块内初始化sam成员变量");
            }
      Test()
      {
            System.out.println("Test默认构造函数被调用");
      }

}
//主函数
 public static void  main(String  str[])
{

     Test a=new Test();

 }
输出结果为:
静态成员sam初始化     -----静态成员初始化
static块执行          -----静态块被执行
静态块内初始化sam成员变量 ----静态块执行
sam1成员初始化      -----普通成员初始化
Test默认构造函数被调用  -----构造函数执行


由此可以得出结论:
静态成员变量首先初始化(注意,Static可以看做一个静态成员,其执行顺序和其在类中申明的顺序有关)
b 普通成员初始化
c 执行构造函数。

对于静态成员(static块可以看成普通的一个静态成员,其并不一定在类初始化时首先执行)和普通成员,其初始化顺序只与其在类定义中的顺序有关,和其他因素无关。
例如下面的例子:


class Test{
      static{
            System.out.println("static 块 1  执行");
            }
      static Sample staticSam1=new Sample("静态成员staticSam1初始化");
      Sample sam1=new Sample("sam1成员初始化");
      static Sample staticSam2=new Sample("静态成员staticSam2初始化");
      static{
            System.out.println("static 块 2  执行");
            }
      Test()
      {
            System.out.println("Test默认构造函数被调用");
      }
      Sample sam2=new Sample("sam2成员初始化");

}


则结果为:
static 块 1  执行
静态成员staticSam1初始化
静态成员staticSam2初始化
static 块 2  执行 
                      --------静态成员
sam1成员初始化
sam2成员初始化
                      --------普通成员
Test默认构造函数被调用
                      --------构造函数


2 Java继承情况下的初始化顺序:

class  Test{
       static {
            System. out .println( "父类static 块 1  执行" );
            }
       static  Sample  staticSam1 = new  Sample( "父类 静态成员staticSam1初始化" );
      Sample  sam1 = new  Sample( "父类 sam1成员初始化" );
       static  Sample  staticSam2 = new  Sample( "父类 静态成员staticSam2初始化" );
       static {
            System. out .println( "父类 static 块 2  执行" );
            }
      Test()
      {
            System. out .println( "父类 Test默认构造函数被调用" );
      }
      Sample  sam2 = new  Sample( "父类 sam2成员初始化" );

}

class  TestSub  extends  Test
{
       static  Sample  staticSamSub = new  Sample( "子类 静态成员staticSamSub初始化" );
      TestSub()
      {
            System. out .println( "子类 TestSub 默认构造函数被调用" );
      }
      Sample  sam1 = new  Sample( "子类 sam1成员初始化" );
       static  Sample  staticSamSub1 = new  Sample( "子类 静态成员staticSamSub1初始化" );
      
       static {System. out .println( "子类 static 块  执行" );}
      Sample  sam2 = new  Sample( "子类 sam2成员初始化" );
}

执行结果:
父类 static 块 1  执行
父类 静态成员staticSam1初始化
父类 静态成员staticSam2初始化
父类 static 块 2  执行
                        --------父类静态成员初始化
子类 静态成员staticSamSub初始化
子类 静态成员staticSamSub1初始化
子类 static 块  执行
                        -------子类静态成员初始化
父类 sam1成员初始化
父类 sam2成员初始化
父类 Test默认构造函数被调用       
                        -------父类普通成员初始化和构造函数执行
子类 sam1成员初始化
子类 sam2成员初始化
子类 TestSub 默认构造函数被调用
                        -------父类普通成员初始化和构造函数执行


由此得出Java初始化顺序结论:
1 继承体系的所有静态成员初始化(先父类,后子类)
2 父类初始化完成(普通成员的初始化-->构造函数的调用)
3 子类初始化(普通成员-->构造函数)


Java初始化顺序如图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值