静态语句块,实例语句块,构造函数的初始化顺序

一,静态语句块的定义

         在一个类中,不属于任何方法体并且以static关键字修饰的语句块,称为静态语句块。

      因为静态语句块常用来进行类变量的初始化,所以也称为静态初始化程序块。

     格式:static{   };

  ♦静态语句块在加载该类时执行一次(此处的类加载是在该类被调用时才进行加载,比如:当要验证的语句和main()方法在一个类中时,此时调用main()方法时,要先对该类进行加载才能调用main()方法,但是若main()方法和要验证的语句不在一个类中时,则先进行main()方法的类的加载和main()方法的调用,然后当后面要调用放了要验证的语句的类时(即new该类对象时),验证类才会被加载)如果一个类中定义了多个静态语句块,则这些语句块将按在类中出现的先后次序运行。

 

 

  二, 程序初始化的优先级:  基类>派生类

                    static>实例块

              即:先执行基类中的static,在执行派生类中的static,在执行基类中的实例块,在执行派生类中的实例块。

                          ♦(前两种static,谁在前,先打印谁)

                         1.private static int i;         //静态变量

                        2.static{    i=5    };            //静态语句块

                      3. public static int a(){       //静态方法

                                };

                   ♦ 静态语句块,静态变量在类加载时运行,静态方法在手动调用时才执行。

                   ♦实例块包括:  int  i=0;    {    };(这两个按先后次序执行)

                           构造函数 (一般最后执行)

                   ♦实例块只有在新new对象后,才执行。

 

 

三,代码实现 -1:

 

 1 public class ObjectInitTest {
 2     {
 3         System.out.println("实例块a");
 4     }
 5     static{
 6         System.out.println("b");
 7     }
 8 
 9     private  int a= methoda();
10     private static int b=methodb();
11     private static int c=4;
12 
13     private static  int  methodb() {
14         System.out.println("静态属性b");
15         System.out.println(b);
16         return 9;
17     }
18     private  int  methoda() {
19         System.out.println("属性a");
20         return 8;
21     }
22     private static  void  methodc() {
23         System.out.println("静态属性c");
24     }
25 
26 
27     public ObjectInitTest(int a,int b) {
28         this.a=a;
29         this.b=b;
30     }
31 
32     {
33             System.out.println("实例块b");
34             System.out.println(a);
35     }
36 
37     public static void main(String[] args) {
38 
39          ObjectInitTest o=new ObjectInitTest(1,2);
40         //System.out.println(a);  //直接调用a和methoda()会出错,因为静态方法不能直接访问所属类的非静态变量和方法
41         //System.out.println(o.methodc());
42         System.out.println(o.methoda());
System.out.println(o.a);  //非静态变量和方法的访问,需要通过对象
43 System.out.println(b); //此处b为静态变量,可在main的静态方法中直接访问 44 } 45 }

 

 

 

               

    运行结果及分析

      

 

        分析:

     

 

 应注意问题:

         1,  因为静态方法的调用不是通过实例对象进行的,静态方法是类级别的,所以在静态

   方法中没有this指针,且不能直接访问所属类的非静态变量和方法,只能访问方法内定义的

   局部变量,自己的参数和静态变量。非静态变量和方法的访问,需要通过对象。

 

 

 

 

 

 

 

 

 

 

         2,main()方法是一个静态方法。如果要在main()方法中访问所在类的成员变量或方法,就必须首先创建相应

   的实例对象。否则只能访问静态方法或变量。

          3,static变量只能用static方法给其赋值,但普通变量随意。

 

 三,代码实现-2

 1 package L13;
 2 class A{    //父类
 3     protected   int a;
 4     protected   int c;
 5 
 6     public A(int a){
 7         this.a=a;
 8         this.c=1;
 9         System.out.println("父类构造函数");
10     }
11     static{   //静态语句块
12         System.out.println("父类静态语句块");
13 
14     }
15     {
16         System.out.println("父类实例语句块");
17     }
18     public void show(){
19         System.out.println("父类方法");
20         System.out.println("a:"+a);
21     }
22     public void show1(){
23         System.out.println("父类独有的方法");
24     }
25 }
26 /**
27  * 派生类B有两部分
28  *      1.从基类继承来的成员(可重新初始化)
29  *      2.自己定义的成员
30  *
31  *      super和this都必须写在第一行
32  *      super();   //在派生类中调用基类构造函数,在派生类方法中必须写在首行
33  *      super.方法名();//在派生类中,当继承下来的基类方法被派生类重写,在派生类中可用super.方法名()来调用基类的方法。
34  */
35 class B extends A{    //B继承A类
36     private int a;
37     private int b;
38     public B(){
39         super(3);   //调用父类的构造方法
40         this.a=2;
41         this.b=2;
42         System.out.println("子类构造函数");
43     }
44     static{   //静态语句块
45         System.out.println("子类静态语句块");
46 
47     }
48     {
49         System.out.println("子类实例语句块");
50     }
51     public void show(){
52         System.out.println("子类方法");
53         System.out.println("a:"+a);            //当父类和子类拥有相同变量时,若直接用a 打印的是子类中的a变量的值
54         System.out.println("a:"+super.a);     //若用super.a调用,当在子类中没有对其进行初始化,则打印的就是父类中变量a的值。
55                                                 //若以初始化,则打印的是初始化后的。
56         System.out.println("c:"+c);            //但子类中没有与父类重复的变量,可直接用c打印变量值。
57     }
58     public void test(){
59         super.show();   //  与变量类似,对于被子类重写了的方法,需用super.方法名()来掉用
60         this.show1();   //对于父类独有的,直接掉用。
61         this.show();
62     }
63 }
64 public class DeriveTest {
65     public static void main(String[] args) {
66         B b=new B();
67         //b.show();    //因为子类方法名与父类相同,且返回值与参数列表也相同,所以被B继承的父类的show()方法已被子类相同方法重写
68                      //所以b.show()打印出来就是子类中show()方法的内容。
69         //b.show1();   //但对于父类独有的方法,当被B类继承下来后,因为没有被重写,所以 b.show1();打印出来的就是父类中方法的内容。
70        // b.test();
71         B c=new B();
72     }
73 
74 }

  运行结果:

 

 

 需注意:

 *          this关键字的两个用法:

 *             1.在构造函数中调用待传入int参数的其它的构造函数,如this( )。

 *        2.在成员方法里面访问其它成员(变量,方法),前面可以添加this.变量/方法。

 *

 *    super关键字的三个用法:

 *       1.在派生类的构造函数中调用基类的带int参数的构造函数 如super( )。

 *       2.super.func() 在派生类中,调用从基类继承来的func方法

 *       3.super.a 在派生类中,调用从基类继承来的名字叫a的成员变量

 

                         super关键字

          在对象的内部使用,可以代表父类对象

          1,访问父类的属性 super.age

          2,访问父类的方法 super.eat()

          3,子类的构造过程中必须调用其父类的构造方法 super();

               ( 如果子类的构造方法中没有显式调用父类的构造方法,则系统默认调用父类无参的构造方法

                    如果显式的调用构造方法,必须在子类构造方法的第1行

                    如果子类构造方法中既没有显示调用父类的构造方法,而父类有没有无参的构造方法,则编译出错。)

         this和super关键字都和对象有关,所以在static方法中不能使用这两个关键字

          

 

  

posted @ 2019-10-11 09:47  小L要努力吖  阅读(719)  评论(0编辑  收藏  举报