java中的初始化块

1.初始化的顺序以及原理


转载于:http://www.cnblogs.com/awkshare/articles/4196551.html


Java使用构造器来对单个对象进行初始化操作,使用构造器先完成整个Java对象的状态初始化,然后将Java对象返回给程序,从而让该Java对象的信息更加完整。与构造器作用非常类似的是初始化块,它也可以对Java对象进行初始化操作
一个类里可以有多个初始化块,相同类型的初始化块之间有顺序:前面定义的初始化块先执行,后面定义的初始化块执行
[修饰符]  {
        //初始化块的可执行性代码
        。。。
}
初始化块的修饰符只能是static,使用static修饰的初始化块被称为静态初始化。初始化块里的代码可以包含任何可执行性语句,包括定义局部变量 ,调用其他对象的方法,以及使用分支,循环语句等
下面定义一个初始化块也有构造器
 
public class Person {
    {//定义第一个初始化块
        int a= 6;//初始化块中
        if (a >4){
            System.out.println("Person初始化块:局部变量a的值大于4");
         }
        System.out.println("Person的初始化块");
}
 
//定义第二个初始化块
{
    System.out.println("Person 的第二个初始化块");
}
//定义无参数的构造器
public Person(){
    System.out.println("Person类的无参数构造器");
}
public static void main(String[] args){
    new Person();
}
}
 
初始化块和构造器
从某种程度上来看,初始化块是构造器的补充,初始化块总是在构造器执行之前执行。
 
初始化块跟构造器不同的是初始化块是一段固定执行的代码,他不能接收任何参数。
通过把多个构造器中的相同代码提取到初始化块中定义,能更好地提高初始化代码的复用,提高整个应用的可维护性
与构造器类似,创建一个Java对象时,不仅会提高该类的图片初始化块和构造器,而且系统会一直上朔到Java.lang.Object类,先执行该类的初始化块,开始执行该类的构造器,一次向下执行器父类的初始化块,开始执行其父类的构造器,最后才执行该类的初始化块和构造器,返回该类的不对象
 
静态初始化块
如果定义初始化块时使用了static修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块。静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行。因此静态初始化块总是比普通初始化块先执行。
 
静态初始化块是类相关的,用于对整个类进行初始化处理,通常用于对类Field执行初始化处理,静态初始化块不能对实例Field进行初始化处理
静态初始化块也被称为类初始化块,也属于类的静态成员,同样需要遵循静态成呢个有不能访问非静态成员的规则,因此静态初始化块不能访问非静态成员,包括不恩那个访问实例Field和实例方法
 
与普通初始化块类似的是,系统在类初始化阶段执行静态初始化块时,不仅会执行本类的静态初始化块,而且还会一直上朔到java.lang.Object了,先执行java.lang.Object类的静态初始化块,然后执行器父类的静态初始化块,最后才执行该类的静态初始化块,经过这个过程,才完成了该类的初始化过程。只有当类初始化完成后,才可以在系统中使用这个类,包括访问这个类的类方法 类Field,或者用这个类来创建实例
 
下面程序创建了三个类:Root,Mid和Leaf,这三个类都提供了静态初始化块和普通初始化块,而且Mid类里还是用this调用重载的构造器,Leaf使用super显式调用其父类指定的构造器
 
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();
        System.out.println("Mid 的带参数构造器,其参数值: " + msg);
    }
}
class Leaf extends Mid {
    static{
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }
    public Leaf(){
        super("疯狂Java讲义");
        System.out.println(" 执行Leaf的构造器");
    }
}
public class Test{
    public static void main(String[] args){
        new Leaf();
        new Leaf();
    }
}
 
普通初始化块和构造器的执行顺序与前面介绍的一致,每次创建一个leaf对象时,都需要先执行最顶层父类的初始化块,构造器,然后执行其父类的初始化块,构造器,最后才执行Leaf类的初始化块和构造器
 
Java系统加载并初始化某个类时,总是保证该类的所有父类(包括直接父类和间接父类)全部加载并初始化。
 


2.初始化块应用场合


转载于:http://blog.csdn.net/bettarwang/article/details/27128323


 对于普通的类而言,可以放在初始化块中的初始化工作其实完全可以放到构造函数中进行,只不过有时会带来些许不便,如有多个构造器,就要在多个地方加上初始化函数完成初始化工作,而如果放到初始化块中的话则只要写一次即可。如下例所示:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.*;  
  2.   
  3. public class Car  
  4. {  
  5.    private void init()  
  6.    {  
  7.       System.out.println("Start engine before run()");  
  8.    }  
  9.       
  10.    public Car()  
  11.    {  
  12.       init();  
  13.       System.out.println("Run normally");  
  14.    }  
  15.      
  16.    public Car(float velocity)  
  17.    {  
  18.       init();  
  19.       System.out.println("Run with "+velocity+" miles/h");  
  20.     }  
  21.   
  22.    public static void main(String[]args)  
  23.    {  
  24.       new Car();  
  25.       new Car(210f);  
  26.    }  
  27. }  
输出结果如下:


如果使用初始化块,则代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.*;  
  2.   
  3. public class Car  
  4. {  
  5.    private void init()  
  6.    {  
  7.       System.out.println("Start engine before run()");  
  8.    }  
  9.       
  10.    //使用初始化块  
  11.    {  
  12.      init();  
  13.     }  
  14.     
  15.   
  16.    public Car()  
  17.    {  
  18.       //init();  
  19.       System.out.println("Run normally");  
  20.    }  
  21.      
  22.    public Car(float velocity)  
  23.    {  
  24.       //init();  
  25.       System.out.println("Run with "+velocity+" miles/h");  
  26.     }  
  27.   
  28.    public static void main(String[]args)  
  29.    {  
  30.       new Car();  
  31.       new Car(210f);  
  32.    }  
  33. }  
显然,使用初始化块的代码比不使用初始化块的代码要更简洁。
但是,如果只是这一点便利的话,还不足以使用初始化块,其实初始化块真正体现其独一无二的作用是在匿名内部类中,由于是匿名内部类,因而无法写构造方法,但是很多时候还是要完成相应的初始化工作,这时就需要用到初始化块了,特别是Android中大量地使用匿名内部类,初始化块的作用就十分突出,如下例所示:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. import java.util.*;  
  2.   
  3. interface Vehicle  
  4. {  
  5.   public void run();  
  6.   public void carry();   
  7.  }  
  8.   
  9. class Person  
  10. {  
  11.   public void drive(Vehicle vehicle)  
  12.   {  
  13.     vehicle.run();  
  14.    }  
  15. }  
  16.   
  17. public class AnonymousSample  
  18. {  
  19.    public static void main(String[]args)  
  20.    {  
  21.       Person person=new Person();  
  22.       person.drive(new Vehicle()  
  23.       {  
  24.         private void init()  
  25.         {  
  26.            System.out.println("Start engine befor run()");  
  27.         }  
  28.           
  29.         //匿名类中只能使用普通初始化块来完成初始化工作  
  30.         {  
  31.           init();   
  32.          }  
  33.   
  34.         @Override  
  35.         public void run()  
  36.         {  
  37.            System.out.println("Car can run with high velocity on freeway.");  
  38.         }  
  39.         @Override  
  40.         public void carry()  
  41.         {  
  42.            System.out.println("Car can carry 3 persons at least.");  
  43.          }  
  44.       });  
  45.    }  
  46. }  
输出结果如下:


显然,在本例中,由于实现Vehicle的匿名内部类没有名字,自然也不能有显式的构造方法,从而无法在构造方法中完成初始化工作,但是如果不完成初始化就无法正常启动,所以此时就要借助初始化块。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值