`
fishermen
  • 浏览: 380139 次
社区版块
存档分类
最新评论

java类中静态域、块,非静态域、块,构造函数的初始化顺序

阅读更多
在《Core java 2: volumn 1, Edition 5》一书的第四章“对象与类”中讲到域赋值语句、实例块、静态块及构造方法等在创建类实例时的执行顺序,中文译本有些处翻译的不贴切,而英文原书中也有一处错误。本文通过一个小程序来说明类实例构造过程中的语句执行顺序。

程序如下:

public class Teststaticblock
{
public Teststaticblock()
{
  this("second");
  System.out.println("begin constructor");
  System.out.println(s_a);
  System.out.println(s_b);
  System.out.println(c);
  System.out.println(d);
//  this("second");//call to this must be first statement in constructor
  s_a=1111;
  s_b=2222;
  c=3333;
  d=4444;
  System.out.println(s_a);
  System.out.println(s_b);
  System.out.println(c);
  System.out.println(d);
  System.out.println("end constructor");
}
public Teststaticblock(String s)
{
  System.out.println("begin second constructor");
  System.out.println("end second constructor");
}
public static void main(String args[])
{
  System.out.println("begin main");
  System.out.println(s_a);
  System.out.println(s_b);
//  System.out.println(c);//non-static variable c cannot be referenced from a static context
//  System.out.println(d);//non-static variable c cannot be referenced from a static context
  s_a=11111;
  s_b=22222;
//  c=33333;//non-static variable c cannot be referenced from a static context
//  d=44444;//non-static variable c cannot be referenced from a static context
  System.out.println(s_a);
  System.out.println(s_b);
//  System.out.println(c);//non-static variable c cannot be referenced from a static context
//  System.out.println(d);//non-static variable c cannot be referenced from a static context
  System.out.println("before new class object");
  Teststaticblock t = new Teststaticblock();
  System.out.println("end new class object");
  System.out.println(s_a);
  System.out.println(s_b);
//  System.out.println(c);//non-static variable c cannot be referenced from a static context
//  System.out.println(d);//non-static variable c cannot be referenced from a static context
  s_a=111111;
  s_b=222222;
//  c=333333;//non-static variable c cannot be referenced from a static context
//  d=444444;//non-static variable c cannot be referenced from a static context
  System.out.println(s_a);
  System.out.println(s_b);
//  System.out.println(c);//non-static variable c cannot be referenced from a static context
//  System.out.println(d);//non-static variable c cannot be referenced from a static context
  System.out.println("end main");
}

static int s_a=1;
int c=3;
{
  System.out.println("begin block");
  System.out.println(s_a);
  System.out.println(s_b);
  System.out.println(c);
//  System.out.println(d);//illegal forward reference
  s_a=111;
  s_b=222;
  c=333;
  d=444;
  System.out.println(s_a);
  System.out.println(s_b);
  System.out.println(c);
//  System.out.println(d);//illegal forward reference
  System.out.println("end block");
}
static
{
  System.out.println("begin static block");
  System.out.println(s_a);
//  System.out.println(s_b);//illegal forward reference
//  System.out.println(c);//non-static variable c cannot be referenced from a static context
//  System.out.println(d);//non-static variable c cannot be referenced from a static context
  s_a=11;
  s_b=22;
  System.out.println(s_a);
//  System.out.println(s_b);//illegal forward reference
//  System.out.println(c);//non-static variable c cannot be referenced from a static context
//  System.out.println(d);//non-static variable c cannot be referenced from a static context
  System.out.println("end static block");
}
int d=4;
static int s_b=2;

}


输出如下:

begin static block
1
11
end static block
begin main
11
2
11111
22222
before new class object
begin block
11111
22222
3
111
222
333
end block
begin second constructor
end second constructor
begin constructor
111
222
333
4
1111
2222
3333
4444
end constructor
end new class object
1111
2222
111111
222222
end main

通过对输出进行分析,可以得出如下结果:
1、在类第一次加载时候,会执行静态域(field)初始化语句和静态块(用static{}包含的部分)。
这里要注意:
    a、不管静态域声明语句的实际位置在哪儿,当第一次加载类的时候都会首先对它初始化为缺省值(0,false,null等)。
    b、即使静态域声明中使用了显式初始化语句(比如:int x=3),第一次加载类的时候也会先把它初始化为缺省值(此时x为0),然后再按照下面说的要点c来执行赋值语句(x=3)。
    c、对于静态域的显式初始化语句和静态块,按照在类中代码出现的先后顺序执行。
     因此,在上面的例子程序中,我们看到
      static int s_a=1;
      static
      {
         s_a=11;
         s_b=22;
       }
       static int s_b=2;
      对s_a,s_b会有不同的效果。类加载时候,s_a,s_b都被初始化为0,然后由于依照代码顺序执行了s_a=1;s_a=11;s_b=22;s_b=2;结果s_a、s_b分别变成了11和2。

2、当构造类实例时候,会先对实例域初始化为缺省值,然后执行实例块(用{}括起来的部分),然后执行构造方法。其中:
    a、如同1中一样,如果有实例域的显式初始化语句,程序仍然是先将该域初始化为缺省值,然后按照代码在类中出现的先后顺序执行初始化语句或者实例块。如果实例块位置在初始化语句前面,即使它改变了该域的值,也会被随后执行的初始化语句改回去。
    b、在进入构造方法后,如果构造方法第一句是使用this(...)调用另一构造方法的话,则先执行另一构造方法,然后再执行本构造方法的方法体。这种用法必须让this(...)位于第一句。

《Core java 2》书中所说的"进入构造方法后,如果第一句是调用别的构造方法,则进入别的构造方法。否则,执行实例块"的提法有问题。事实是,不管是否使用this()都会先执行实例块,再进入构造方法。另外,本程序需要在sdk1.4下编译,在sdk1.3下编译将不允许在静态块或实例块中改变位置在它们后面声明的域的值。
分享到:
评论

相关推荐

    【Java】80例及结果

    从提供的【部分内容】中,我们可以提炼出Java语言中面向对象编程的几个核心概念,包括类的继承、构造函数的执行顺序、静态属性的初始化顺序、以及变量的作用域等方面的知识点。以下是详细解释: 1. 类的继承与构造...

    静态代码块

    在Java编程语言中,代码块是一种用于对对象或类进行初始化的有效手段。根据它们的作用域和执行时机的不同,代码块可以分为几种类型,其中最常见的两种是静态代码块(static code block)和构造代码块(instance ...

    JAVA函数使用手册

    12. **构造函数**:特殊类型的函数,用于初始化新对象。类可以有多个构造函数,根据参数列表进行重载。 13. **函数式编程**:Java 8引入了对函数式编程的支持,如Stream API,使得处理集合数据变得更加简洁和高效。...

    java代码块测试

    3. **静态初始化块**:当类被加载到JVM(Java虚拟机)时,这些代码块被执行。它们用于初始化类级别的变量,不依赖于类的实例。 4. **finally代码块**:用于异常处理,无论是否抛出异常,finally块中的代码总会被...

    java 函数速查CHM

    6. **构造函数**:特殊类型的函数,用于对象的初始化。类名与构造函数相同,没有返回类型。 7. **匿名函数**:Java 8引入了Lambda表达式,允许创建没有名字的函数,常用于函数式接口。 8. **递归**:函数调用自身...

    Java基础知识面试题系列一.docx

    3. **Java程序初始化顺序**:初始化顺序遵循以下原则: - 首先初始化静态变量和静态代码块,按定义顺序执行。 - 其次是父类的非静态部分,包括非静态变量和非静态代码块,再是父类构造函数。 - 最后是子类的非...

    java代码-日常练习33,代码块### 静态代码块 static{代码内容;} 随着类的加载就执行一次 构造器代码块 {代码内容;} 每创建对象就执行一次 局部代码块 {代码内容;} 方法执行一次执行一次

    在Java编程语言中,代码块是程序中一组按顺序执行的语句,它们可以有特定的作用域和执行时机。在日常练习33中,我们关注的是三种不同类型的代码块:静态代码块、构造器代码块和局部代码块。下面将详细讲解这三种代码...

    《Java 语言程序设计》阶段测试题

    在Java中,一个类的构造函数用于初始化该类的对象,并且在创建对象时自动调用。然而,如果构造函数中使用了与类中的变量同名的局部变量,则构造函数内部的变量将隐藏类中的变量。因此,在试题2中,尽管构造函数中...

    Java课件1

    默认构造函数没有参数,而自定义构造函数可以带有参数以进行初始化。例如,`Circle`类可以定义不同的构造函数,以处理不同半径的圆。 9.3 构造函数: 构造函数没有返回类型,名称与类名相同,主要用于对象初始化。...

    Java语言编码规范.pdf

    - 变量初始化的最佳时机和顺序,例如局部变量应在声明时初始化,而成员变量可以在声明时或构造函数中初始化。 - 对象的创建和初始化,包括构造函数的使用规则,以及如何使用静态代码块和实例代码块进行复杂的初始化...

    java1-6章测试题目.pdf

    26. **创建对象的内部过程**:分配内存、调用构造函数初始化、返回对象引用。 27. **值传递与引用传递**:Java中,对象作为参数传递实际上是引用传递,但不能改变对象本身,只能修改对象的内容。 28. **常用类、包...

    java学习笔记

    5. **构造函数**:构造函数是类的一个特殊方法,用于初始化新创建的对象。默认情况下,如果程序员没有定义构造函数,JVM会提供一个无参构造函数,不做任何操作。但一旦程序员自定义了构造函数,JVM就不会再生成默认...

    比较全面的JAVA面试题

    11. **继承时类的执行顺序**:首先执行父类的静态初始化块,然后执行子类的静态初始化块,接着执行父类的非静态初始化块和构造函数,最后执行子类的非静态初始化块和构造函数。 12. **内部类的实现方式**:包括成员...

    《JAVA语言程序设计》期末考试试题及答案2(应考必备题库)

    7. **静态初始化器**:静态初始化器(静态块)在类加载时执行,用于初始化静态成员。 8. **对象赋值**:Java中对象赋值实际上是创建了一个新对象的引用,并非复制整个对象。赋值操作不会生成属性相同的“新对象”。...

    java 面试题

    3. **父类非静态初始化块**:然后执行父类中的非静态初始化块。 4. **父类构造函数**:随后执行父类的构造函数。 5. **子类非静态初始化块**:接下来执行子类中的非静态初始化块。 6. **子类构造函数**:最后执行...

    1_java-选择题不带答案.doc

    6. 构造函数:Java 中,构造函数用于初始化类的新实例。A 错误,因为类可以没有显式定义的构造函数,Java 会提供一个默认的无参构造函数。B 错误,构造函数没有返回类型。C 错误,构造函数可以带参数。D 正确,类...

    java期末考试知识点总结.doc

    4. **初始化顺序**:先初始化基类的属性,然后是派生类自己的属性。 5. **构造方法的重载**:构造函数可以被重载,即在一个类中可以有多个构造函数,但它们的参数列表不同。 #### 七、类的修饰符 1. **Public类**...

    java笔记 java笔记

    - **局部变量**:在方法、构造函数或块内声明的变量。 - **成员变量**:在类体中声明的变量。 ##### 4.2 操作符 Java支持多种操作符,包括算术操作符、比较操作符、逻辑操作符等。 ##### 4.3 数字类型之间的转换 ...

    U201814655-CS1806-杨雨鑫-第五次作业1

    【知识点详解】 1. 访问修饰符:在Java中,...这些知识点涵盖了类的成员访问控制、构造函数、对象初始化、`this`关键字的使用、继承中的访问权限以及Java的数据类型等方面的内容,对于理解和编写Java代码至关重要。

Global site tag (gtag.js) - Google Analytics