静态初始化块

来源:互联网 发布:日本殖民地知乎 编辑:程序博客网 时间:2024/06/04 23:32

在写静态初始化块的同时,我要先写另一个相对来说比较重要的一个概念;
子类对象和父类对象的转换,和基本类型之间的强制类型转换一样,存在继承关系的父类对象和子类对象也可以在一定条件下相互转换。
转换规则如下:
1、子类对象可以被视为其父类的一个对象。
2、父类对象不能被当做是某一个子类的对象;
3、如果一个方法的形参定义的是父类对象,那摩调用这个方法时,可以使用子类对象作为实际参数。
4、如果父类对象与引用指向的实际是一个子类对象,那摩这个父类对象的引用可以用强制类型转换转换成子类对象的引用。格式:(子类名)父类名;
例;
public class Person
{
   String str="Person";
   public void print()
 {
          System.out.print("父类print()方法,对象是:"+this.toString);
        }

}
public class Student extends Person
{
  String str="Student";
  public void print()
      {
        System.out.print("子类print()方法,对象:+this.toString);
          }
}
public class StudentText
{
      public static void main(String[] args)
 {
           Person p1 = new Person();
           System.out.println("Person变量p1.str="+p1.str);    //输出Person变量p1.str=Person
           System.out.print("Person对象调用print()的结果:");
           p1.print();     //Person对象调用print()的结果:父类print()方法,对象是:Person
    Student s1 = new Student();
           System.out.println("Student变量s1.str="+s1.str);   //输出Student变量s1.str=Student
           System.out.print("Student对象调用print()的结果:");
           s1.print();     //Student对象调用print()的结果:子类print()方法,对象是:Student
    Person p2 = new Student();
           System.out.println("Person变量p2.str="+p2.str);  //输出Person变量p2.str=Person
           System.out.print("Person对象p2调用print()的结果:"); //Person对象调用print()的结果:子类print()方法,对象是:Student
           p2.print();
        }
}

从上面结果得出:
多态中成员方法的特点:
在编译时,看引用类型的类是否有此方法;
在运行时,看对象所在的类是否有调用的方法。(动态绑定)
 
   编译看左边,运行看右边。
多态中成员变量的特点:编译和运行都看左边。

讲一个用或者不用的一个运算符:
 instanceof运算符

 调用方法时如果实参是子类Student的对象,则造型是正确的,若实参是父类Person的对象,则造型失败!

       if(p instanceof Student){
 
                  Student st=(Student)p;
 
  st.display();

       }


运算符instanceof用于检测一个对象的真正类型。
格式:<变量名> instanceof <类型>

功能:如果instanceof操作符左侧的变量当前时刻所引用对象的真正类型是其右侧给出的类型、或是其子类,则整个表达式结果为true,否则结果为false。

下面来写静态初始化块恩恩:

Java使用构造方法来对单个对象进行初始化操作。与构造方法作用非常类似的是初始化块,它也可以对对象进行初始化操作。

  初始化块是Java类里可以出现的第四种成员。语法格式:

 class 类名{

  [修饰符]{

   //初始化块的可执行代码//可以定义局部变量、调用其他对象的方法、使用分支、循环语句等


  }

  …
 
 }

一个类里可以有多个初始化块;
相同类型的初始化块之间有顺序,前面定义的初始化块先执行,后面定义的初始化块后执行。


当创建Java对象时,系统总是先调用该类里定义的初始化块;
如果一个类里定义了两个普通初始化块,则前面定义的初始化块先执行,后面定义的初始化块后执行。

初始化块虽然也是Java类里的一种成员,但它没有名字,也就没有标识,因此无法通过类、对象来调用初始化块;
初始化块只能在创建对象时自动执行而且在执行构造方法之前执行。


 初始块和声明实例属性时所指定的初始值都是该实例的初始化代码,它们的执行顺序与源程序中排列顺序相同。

 初始化块和构造方法的不同:初始化块是一段固定的执行代码,它不能接受任何参数。因此初始化块对同一个类内的属性所进行的初始化处理完全相同。
    
 用法:如果多个构造方法里有相同的初始化代码,这些代码无需接受参数,那就可以把他们放在初始化块中定义。能更好的提高初始化块的复用,提高整个应用的可维护性。
    
 创建一个Java对象时,不仅会执行该类的初始化块和构造方法,系统会先执行其父类的初始化块和构造方法。


如果定义初始化块时使用了static修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块。

静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行,因此静态初始块总是比普通初始化块先执行。

静态初始块属于类的静态成员,用于对类属性执行初始化处理,不能对实例属性进行初始化处理。
系统在类初始化阶段执行静态初始化时,不仅会执行本类的静态初始化块,还会一直上溯到Object类(如果它包含静态初始化块)。
经过这个过程,才完成了对类的初始化过程。 

下面我讲一个实例写下来:

 

class Root
{
 static
 {
 System.out.println("Root的静态初始化模块");//1//系统将在类初始化阶段执行静态初始化块
 }
 {
 System.out.println("Root的普通初始化模块");//4  //11
 }
 public Root()
 {
 System.out.println("Root的无参数的构造方法");//5//12
 }
}
class Mid extends Root
{
 static
 {
 System.out.println("Mid的静态初始化块");//2
 }
 {
 System.out.println("Mid的普通初始化块");//6//13
 }
 public Mid()
 {
 System.out.println("Mid的无参数的构造方法");//7//14
 }
 public Mid(String msg)
 {
 this();
 System.out.println("Mid的带参数构造方法,其参数值:"+msg);//8//15
 }
}
class Leaf extends Mid
{
 static
 {
 System.out.println("Leaf的静态初始化块");//3
 }
 {
 System.out.println("Leaf的普通初始化块");//9//16
 }
 public Leaf()
 {
 super("Struts2权威指南");
 System.out.println("执行Leaf的构造方法");//10//17
 }
}
public class Test
{
 public static void main(String[]args)
 {
 new Leaf();
 new Leaf();
 }
}

输出结果会是什么呢:有序号代表;