Java类的初始化

Java提供了两种不同的初始化类型,分别是类的初始化和对象的初始化。类成员都是静态的,默认会设置一个值。对象的初始化会在构造函数里面进行。但如果想要赋给静态变量非默认值,或者是初始化一类共有的对象属性(不论调用哪个构造函数),那么就需要一些特殊的方法。提供了静态初始化块和非静态初始化块来处理这两种情况.

  1. 静态初始化块

静态初始化块是通过static{}来定义的。一个简单的代码示例如下:

public class CorderStatic {
staticint idx;

static{
    System.out.println("idx: " + Integer.toString(idx++));
    System.out.println("idx: " + Integer.toString(idx));
}

publicstatic void main(String[] argv) {
    System.out.println("DONE");
}
}

代码运行的结果是:


idx: 0

idx: 1

DONE

从输出结果可以看出静态初始化块在静态成员的初始化后调用。而且如果类中存在多个静态初始化块,则根据出现的次序进行调用。

  1. 非静态初始化块

非静态初始化块定义在{}块中。其与静态初始化块的区别是没有static关键字修辞。测试代码如下:

public class CorderInstance {
    int idx;

{
    System.out.println("idx: " + Integer.toString(idx++));
    System.out.println("idx: " + Integer.toString(idx++));
}

publicCorderInstance() {
    System.out.println("idxin constructor : " + Integer.toString(idx));
}

public static void main(String[] argv) {
    newCorderInstance();

    System.out.println("DONE");
}
}

代码输出如下:


idx: 0

idx: 1

idxin constructor : 2

DONE

可见,非静态初始化块在对象属性初始化结束,构造函数调用前被调用。

  1. 初始化顺序

如果一个类里面定义了静态和非静态的初始化块,哪个会先被执行呢?测试代码如下:

public class Corder {
static int staticpro;

static{
    System.out.println("staticblock : " + Integer.toString(staticpro));
}

int instancepro;

{
    System.out.println("non-staticblock." + Integer.toString(instancepro++));
}

publicCorder() {
    System.out.println("instanceproperty : " + Integer.toString(instancepro++));
    System.out.println("Theconstructor had been complete.");
}

publicstatic void main(String[] argv) {
    newCorder();
}
}

代码输出如下:


staticblock : 0

non-staticblock.0

instanceproperty : 1

Theconstructor had been complete.

可见,静态初始化块会先被调用,然后是非静态初始化块,最后是构造函数。

  1. 继承与初始化

初始化块在遇到类继承时,情况要变得复杂一些。先把测试代码贴出来:

public class CorderInherit {
static int staticpro;
staticA a;

static{
    System.out.println("staticinitialization : " + Integer.toString(staticpro));

    if(a == null) {
        System.out.println("classa is null.");
    }

    a= new B(10);
}

intinstancepro;
A aa;

{
    instancepro= 10;
    System.out.println("specialblock." + Integer.toString(instancepro));
    aa= new B(10);
}

publicCorderInherit(int i) {
    System.out.println("instanceproperty : " + Integer.toString(instancepro));
    instancepro= i;

    System.out.println("staticproperty : " + Integer.toString(staticpro));
    System.out.println("instanceproperty : " + Integer.toString(instancepro));

    System.out.println("Theconstructor had been complete.");
}

    publicstatic void main(String[] argv) {
        newCorderInherit(-1);
    }
}

class A {
    static int index;

    static{
        System.out.println("ClassA static 1 " + Integer.toString(index++));
    }

    {
        System.out.println("ClassA special 1 " + Integer.toString(index++));
    }

    public A() {
        System.out.println("constructclass A." + Integer.toString(index++));
    }

    static{
        System.out.println("classA static 2 " + Integer.toString(index++));
    }

    {
        System.out.println("ClassA Special 2 " + Integer.toString(index++));
    }
}

class B extends A {
     static int index;

     static{
         System.out.println("ClassB static 1 " + Integer.toString(index++));
     }

     {
         System.out.println("ClassB special 1 " + Integer.toString(index++));
     }

     public B(int i) {
         System.out.println("constructclass B." + Integer.toString(index++));
     }

     static{
         System.out.println("classB static 2 " + Integer.toString(index++));
     }

     {
         System.out.println("ClassB Special 2 " + Integer.toString(index++));
      }
}

代码输出如下:


staticinitialization : 0

classa is null.

ClassA static 1 0

classA static 2 1

ClassB static 1 0

classB static 2 1

ClassA special 1 2

ClassA Special 2 3

constructclass A.4

ClassB special 1 2

ClassB Special 2 3

constructclass B.4

specialblock.10

ClassA special 1 5

ClassA Special 2 6

constructclass A.7

ClassB special 1 5

ClassB Special 2 6

constructclass B.7

instanceproperty : 10

staticproperty : 0

instanceproperty : -1

Theconstructor had been complete.

观察上面的输出,可以看出,当实例化B的对象时,虚拟机会加载B.class,但因为B继承A,所以A.class也会被加载。这就导致A和B的静态初始化块被分别调用。构造B的对象时,A的非静态初始化块和默认构造函数都会被调用,然后才是B的非静态初始化块和构造函数。

  1. 结论

通过上面的例子可以看出,类的完整初始化顺序如下(子类为当前类,或者要new的类):

  1. 给父类的静态成员赋默认值
  2. 按出现顺序调用父类的静态初始化块
  3. 给子类的静态成员赋默认值
  4. 按出现顺序调用子类的静态初始化块
  5. 赋给父类对象属性默认值
  6. 按顺序调用父类对象的非静态初始化块
  7. 调用父类构造函数
  8. 赋给子类对象属性默认值
  9. 按顺序调用子类对象的非静态初始化块
  10. 调用子类构造函数

Java类的初始化,布布扣,bubuko.com

时间: 2024-10-25 12:28:45

Java类的初始化的相关文章

java类的初始化顺序

java类的初始化顺序 (2008-10-21 13:30:15) 转载▼ 标签: java 初始化 继承初始化 it 分类: Java 对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器.我们也可以通过下面的测试代码来验证这一点: public class InitialOrderTest { // 静态变量 public static String staticField = "静态变量";

java类的初始化和构造函数

本人小白一枚,看java类的初始化的时候好晕的说,我觉着书上虽然说的对,但总觉得有些信息没说出来,没说清楚,看了好多文章博客的,现在有些感悟,来小写下总结,也算是为以后再次复习种个好果子. 先摘一下书上写的: 加载:将类的class文件读入内存,并为之创建一个java.lang.class对象. 连接:把类的二进制数据合并到JRE中,检查被加载的类是否有正确的内部结构,并和其他类协调一致.为类的静态FIELD分配内存,设置默认值,将类的二进制数据中的符号引用替换成直接引用. 初始化:主要对静态F

java类内容初始化顺序

在java类中一般有:成员变量.静态变量.成员方法.静态方法.构造方法.那么这几个的初始化顺序是什么呢? 初始化的先后顺序是:静态变量(类load进内存就初始化)------静态代码块(类load进内存就初始化)--------成员变量(对象初始化时)------------初始化块------------构造函数 测试程序如下: package com.evan; /* * 初始化顺序测试 */ public class InitialOrderTest { public static Str

java类的初始化和对象的创建顺序

学习java编程思想--类的初始化p146 类的加载顺序* 1加载器启动找到 xxx.class文件,通过extends关键字寻找基类,先加载基类* 2类初始化先初始化static成员变量和static--->* 2先初始化父类的static成员变量和static* 3再初始化本类的static成员变量和static * 类加载之后,对象创建开始* 1先加载父类的非静态成员变量(静态成员变量在类初始化的时候已经加载,非静态成员变量要随对象的创建而初始化)* 2先加载父类的构造函数* 3再加载本类

[Java] 类的初始化步骤

前言 类的初始化过程,可在多线程环境下进行的,为了简化,本文介绍的单线程情况下的类初始化步骤. 此外,继承情况下的顺序不是本文焦点,本文重点在于一个类的内部字段的初始化顺序. "初始化" 一词,专门针对一个类而言.一个实例被创建过程中,实例字段被初始赋值,不称为初始化,而是直接称作实例的创建,以示区分. 正文 类的初始化,包括静态代码块的初始化.静态字段(类的字段)的初始化. 类的初始化触发条件: 1) T 是一个类,且 T 的一个实例被创建. 2) T 的一个静态方法被调用 3) T

Java类的初始化过程及清理

一.类的数据成员初始化 Java中类的数据成员初试化可能有两种形式. 在定义类成员变量的地方直接提供初始化值(这是C++中不允许的) 在构造器中初试化.(Java中不存在类似C++中的初始化列表) 两者的区别是,第一种方式是数据成员直接初试化为提供的初始化值,而在构造器中初始化,其实在数据成员已经初试化为默认值(比如基本类型如int 初始化为0,引用类型初试为null,其实在在构造器已经不能称为初始化了,应该是赋值) 初始化顺序 如果有静态变量则先初始化静态变量,如果基类中也有静态变量且之前没有

Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)(转)

大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果.这实际上是在考查我们对于继承情况下类的初始化顺序的了解. 我们大家都知道,对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序以此是(静态变量.静态初始化块)>(变量.初始化块)>构造器.我们也可以通过下面的测试代码来验证这一点: Java代码 p

java类的初始化块/执行顺序,实例化对象数据赋值

java里初始化一个类的对象,通过初始化快或者构造方法进行数据赋值.与其相关的执行代码有这么几种: 静态初始化块 初始化块 构造方法 静态初始化块 静态初始化块只在类加载时执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量. 非静态初始化块 非静态初始化块在每次初始化实例对象的时候都执行一次,可以给任意变量赋值. 构造方法 在每次初始化实例对象时调用. 重点:执行顺序-> 在加载类时执行一次静态初始化块(之后不再调用). 在每次初始化实例对象时:先执行非静态初始化块,再执行构

java类的初始化过程

转自http://blog.csdn.net/monghuan/article/details/7404670 一个类可以使用不包含在任何方法体中的静态代码块,当类被载入时,静态代码块被执行,且只被执行一次,静态块常用来执行类属性的初始化. 一.类加载时,变量的初始化顺序:  1.首先,给静态成员变量分配内存空间,进行默认初始化   (整型为0,浮点型为0.0,布尔型为false,字符型为'\u0000',引用型为null)     2.其次,执行静态成员变量的初始化操作   --静态成员的初始