博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
构造器,代码块,继承
阅读量:6238 次
发布时间:2019-06-22

本文共 3853 字,大约阅读时间需要 12 分钟。

hot3.png

1.类初始化阶段,类执行最顶层父类的静态初始化块,依次向下,最后执行当前类静态初始化块。

class Root {   static{  //静态初始化块      System.out.println("Root的静态初始化块");   }   {        //普通初始化块      System.out.println("Root的普通初始化块");   } }class Mid extends Root{  static{       System.out.println("Mid的静态初始化块");   }   {       ystem.out.println("Mid的普通初始化块");   }  }class Leaf extends Mid{   static{       System.out.println("Leaf的静态初始化块");   }   {       System.out.println("Leaf的普通初始化块");   }   }public class test{   public static void main(String[] args)    {       new Leaf();     }}

如上,首先执行顶层父类Root的静态初始化块,然后依次向下,即是Mid,和leaf的静态初始化块.然后再执行顶层父类Root的普通初始化块与构造器。

静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行。因此静态初始化块总是比普通初始化块先执行。 另外,一旦某类的类初始化成功后,该类就会在虚拟机中一直存在,因此第二次创建该类的实例时,无需再次对该类进行类初始化

如例5中的 new Leaf(); new Leaf();
第一次new Leaf()时系统会自动初始化Leaf类,完成后再次创建Leaf实例时,就无需再进行类初始化步骤,即无需再输出处于该步骤的静态初始化块的内容。 总而言之,两次new Leaf()只输出一次静态初始化块的内容。 

2.对象初始化阶段,先执行最顶层父类的普通初始化块、构造器,依次向下,最后执行当前类普通初始化块、构造器。
class Root {     {        //普通初始化块      System.out.println("Root的普通初始化块");   }   public Root()   {      System.out.println("Root的无参数的构造器");   }}class Mid extends Root{   {       System.out.println("Mid的普通初始化块");   }   public Mid()   {       System.out.println("Mid的无参数的构造器");   }  }class Leaf extends Mid{     {       System.out.println("Leaf的普通初始化块");   }    public Leaf()   {  System.out.println("执行Leaf的构造器");   }}public class test{   public static void main(String[] args)    {       new Leaf();         }}
如上代码,程序先执行顶层父类Root中的普通初始化块,再执行Root的构造器。这里有点注意的是,
执行顺序与初始化块和构造器在类中
的相对
位置无关。若类中的构造器在普通初始化块之前,对象初始化时依旧先执行普通初始化块,再执行构造器。

然后再依次执行Mid类的普通初始化块、构造器;最后执行Leaf类的普通初始化块、构造器。 

3.构造器.

class Root {     public Root()   {      System.out.println("Root的无参数的构造器");   }}class Mid extends Root{    public Mid()   {       System.out.println("Mid的无参数的构造器");   }   public Mid(String msg)   {             System.out.println("Mid的带参数构造器,其参数值:" + msg);   }}class Leaf extends Mid{     public Leaf()   {              System.out.println("执行Leaf的构造器");   }}public class test{   public static void main(String[] args)    {       new Leaf();       }}

创建对象时,如果子类的构造器中没有通过super调用父类的有参构造器,也没有通过this调用自身的其他构造方法,则系统会默认先调用父类的无参构造器。 为了方便起见,可以当做每个无参构造器中都有一句super();

如上代码,需要创建Leaf类的实例时,系统会自动调用顶层父类Root的无参构造器,然后依次向下调用各父类的无参构造器,即Mid(),最后调用本身的Leaf().
因此最后输出为:
Root的无参数的构造器
Mid的无参数的构造器
执行Leaf的构造器

4.调用父类构造器.

class Root{		public Root()	{		System.out.println("Root的无参数的构造器");	}}class Mid extends Root{		public Mid()	{		System.out.println("Mid的无参数的构造器");	}	public Mid(String msg)	{		//通过this调用同一类中重载的构造器		this();		System.out.println("Mid的带参数构造器,其参数值:" + msg);	}}class Leaf extends Mid{		public Leaf()	{		//通过super调用父类中有一个字符串参数的构造器		super("Struts2权威指南");		System.out.println("执行Leaf的构造器");	}}public class Test{	public static void main(String[] args) 	{		new Leaf();	}}

若无参构造器中调用了重载的有参构造器,则优先执行被调用的有参构造器,不执行无参构造器。

例如上述代码,new Leaf()创建Leaf类的对象时,需要调用Leaf类的构造器,而Leaf()中使用super("Struts2权威指南")调用了父类Mid的有参构造器Mid(String msg)。而Mid(String msg)中又通过this()调用了自身的无参构造器Mid(),根据例3中的结论,得知系统可通过Mid()自动调用父类Root的无参构造器Root()

输出:

Root的无参数的构造器
Mid的无参数的构造器
Mid的带参数构造器,其参数值:Struts2权威指南
执行Leaf的构造器

5.初始化块与构造器混合时.

class Root{	static{		System.out.println("Root的静态初始化块");	}	{		System.out.println("Root的普通初始化块");	}	public Root()	{		System.out.println("Root的无参数的构造器");	}}class Mid extends Root{	static{		System.out.println("Mid的静态初始化块");	}	{		System.out.println("Mid的普通初始化块");	}	public Mid()	{		System.out.println("Mid的无参数的构造器");	}	public Mid(String msg)	{		//通过this调用同一类中重载的构造器		this();		System.out.println("Mid的带参数构造器,其参数值:" + msg);	}}class Leaf extends Mid{	static{		System.out.println("Leaf的静态初始化块");	}	{		System.out.println("Leaf的普通初始化块");	}		public Leaf()	{		//通过super调用父类中有一个字符串参数的构造器		super("Struts2权威指南");		System.out.println("执行Leaf的构造器");	}}public class Test{	public static void main(String[] args) 	{		new Leaf();		new Leaf();	}}

执行结果:

转载于:https://my.oschina.net/hillfly/blog/160525

你可能感兴趣的文章