`

类初始化(静态方法及静态域)

阅读更多

注意,有一点很有意思,当使用“.class”来创建对Class对象的引用时,不会自动地初始化该Class对象。

 

为了使用类而做的准备工作实际包含三个步骤:

1.加载 。这是由类加载器执行的。该步骤将查找字节码,并从这些字节码中创建一个Class对象。

2.链接 。这个阶段将验证类中的字节码,为静态域分配存储空间,并且如果必需的话,将解析这个类创建的对其他类的所有引用。

3.初始化 。如果该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化块。

 

 

初始化被延迟到对静态方法(构造器隐式地是静态的)或者非常数静态域进行首次引用时才执行:

 

import java.util.*;

class Initable {
  static final int staticFinal = 47;
  static final int staticFinal2 =
    ClassInitialization.rand.nextInt(1000);
  static {
    System.out.println("Initializing Initable");
  }
}

class Initable2 {
  static int staticNonFinal = 147;
  static {
    System.out.println("Initializing Initable2");
  }
}

class Initable3 {
  static int staticNonFinal = 74;
  static {
    System.out.println("Initializing Initable3");
  }
}

public class ClassInitialization {
  public static Random rand = new Random(47);
  public static void main(String[] args) throws Exception {
    Class initable = Initable.class;
    System.out.println("After creating Initable ref");
    // Does not trigger initialization:
    System.out.println(Initable.staticFinal);
    // Does trigger initialization:
    System.out.println(Initable.staticFinal2);
    // Does trigger initialization:
    System.out.println(Initable2.staticNonFinal);
    Class initable3 = Class.forName("Initable3");
    System.out.println("After creating Initable3 ref");
    System.out.println(Initable3.staticNonFinal);
  }
} 

/* Output:
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74
*///:~

 

1.从initable引用的创建中可以看到,仅使用.class语法来获得对类的引用不会引发初始化。

 

2.Class.forName()的方法立即进行了初始化,如initable3的引用的创建。

 

3.如果一个static final值是“编译期常量”,就像Initable.staticFinal,那么这个值不需要对Initable类进行初始化就可以被读取。

 

4.如果只是将一个域设置为static final,还不足以确保这种行为,例如,对Initable.staticFinal2的访问将强制进行类的初始化,因为它不是一个编译期常量。

 

5.如果一个static域不是final的,那么对它访问时,总是要求在它被读取之前,要先进行链接(为这个域分配存储空间)和初始化(初始化该存储空间   ),就像对Initable2.staticNonFinal的访问所看到的那样。

分享到:
评论
8 楼 lovewhzlq 2009-09-04  
是的,初始化只有一次
7 楼 Anddy 2009-09-04  
System.out.println("--------------");
    System.out.println(Initable3.staticNonFinal);
    System.out.println("--------------");
    Class initable3 = Class.forName("javaeye.Initable3");


/* Output:
--------------
Initializing Initable3
74
--------------
这里没有Class.forName("javaeye.Initable3")初始化的输出!是因为Initable3已经初始化了吧。

*///
6 楼 Anddy 2009-09-04  
你好牛X...java学的好深啊!
[size=medium]传点经验![/size]
5 楼 lovewhzlq 2009-09-04  
晕倒,你加了包名啦javaeye

Class initable3 = Class.forName("Initable3");   这里就要修改代码了

Class initable3 = Class.forName("javaeye.Initable3");  
4 楼 Anddy 2009-09-04  
package javaeye;


import java.util.*;

class Initable {
  static final int staticFinal = 47;
  static final int staticFinal2 =
    Initialize.rand.nextInt(1000);
  static {
    System.out.println("Initializing Initable");
  }
}

class Initable2 {
  static int staticNonFinal = 147;
  static {
    System.out.println("Initializing Initable2");
  }
}

class Initable3 {
  static int staticNonFinal = 74;
  static {
    System.out.println("Initializing Initable3");
  }
}

public class Initialize {
  public static Random rand = new Random(47);
  public static void main(String[] args) throws Exception {
    Class initable = Initable.class;
    System.out.println("After creating Initable ref");
    // Does not trigger initialization:
    System.out.println(Initable.staticFinal);
    // Does trigger initialization:
    System.out.println(Initable.staticFinal2);
    // Does trigger initialization:
    System.out.println(Initable2.staticNonFinal);
    Class initable3 = Class.forName("Initable3");
    System.out.println("After creating Initable3 ref");
    System.out.println(Initable3.staticNonFinal);
  }
} 

/* Output:
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74
*///:~


类路径下有“Initable3.class”
3 楼 lovewhzlq 2009-09-04  
应该不至少,你看看类路径下有没Initable3.class文件
2 楼 Anddy 2009-09-04  
怎么报错...
1 楼 Anddy 2009-09-04  
引用
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Exception in thread "main" java.lang.ClassNotFoundException: Initable3
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at javaeye.Initialize.main(Initialize.java:40)

相关推荐

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

    java类中静态域、块,非静态域、块,构造函数的初始化顺序,通过本例子,能够清楚了解到java类的初始化顺序

    C++类的静态成员初始化详细讲解

    通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化

    java初始化和清理

    Java 的初始化问题和...《Thinking in java》把这种“需要”概括为创建第一个对象时或首次访问静态域或静态方法 时。Sun 公司说类初始化的时机是“initialize on first actice use”, (在首次主动使用时初始 化)。

    实验03 Java面向对象编程1.doc

    ○2在Student类建立构造方法初始化各域的值,并统计学生人数count; ○3创建分别获得各域(学号,姓名,性别和年龄)的public方法,以及分别设置各域(学号,姓名,性别和年龄)值的public方法(即get、set方法);...

    JAVA资格认证:SCJP310-055中文

    第一部分:声明、初始化、和作用域。  定义类、内部类、静态类、接口、枚举。  正确使用包语句和导入语句,包括静态导入。  实现或继承一个或多个接口。  定义、继承抽象类。声明、初始化并使用基本类型、...

    C++类内静态函数和静态成员的小例子

     静态成员不是某对象私有的(所有对象共有,修改一个对象的静态成员,其他所有的都修改,同时这也是RTTI的原理),他要求在声明时初始化(不能在类作用域内初始化),并且, 这个成员也不计算在calss的大小里面(你...

    php中的静态变量的基本用法

    静态变量只存在于函数作用域内,静态变量只存活在栈中。一般的函数内变量在函数结束后会释放,比如局部变量,但是静态变量却不会。... //这里定义并初始化一个静态变量 $nums public static $nums=0; func

    C++静态成员变量和静态成员函数的使用方法总结

    所以,静态数据成员的定义(初始化)不应该被放在头文件中。 其定义方式与全局变量相同。举例如下: xxx.h文件 class base{ private: static const int _i;//声明,标准c++支持有序类型在类体中初始化,但vc6不支持...

    Java 基础核心总结 +经典算法大全.rar

    类的初始化 成员初始化 构造器初始化初始化顺序 数组初始化 对象的销毁 对象作用域 this 和 super 访问控制权限继承 多态组合代理 向上转型static final 接口和抽象类接口 抽象类异常 认 识 Exception 什么是 ...

    学习C#静态函数及变量的一个精典例子与代码

    (1)用于对静态字段、只读字段等的初始化。 (2)添加static关键字,不能添加访问修饰符,因为静态构造函数都是私有的。 (3)类的静态构造函数在给定应用程序域中至多执行一次:只有创建类的实例或者引用类的...

    编程思想下篇

    5.7.3. 显式的静态初始化 5.7.4. 非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 第7章 复用类 第8章 多态 第9章 接口 第10章 内部类 第11章 持有对象 第12章 通过...

    Thinking in java4(中文高清版)-java的'圣经'

    非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 第7章 复用类 第8章 多态 第9章 接口 第10章 内部类 第11章 持有对象 第12章 通过异常处理错误 第13章 字符串 第...

    [原创]基于FLASH机制实现的不同域窗口相互调用js的插件-虫洞

    6)静态类的初始化方法中,对于FLASH插件的载入采用了第三方资源:SWFObject类提供的方法,可根据浏览器的不同而进行不同的装载方式。在Wormhole.js脚本文件中,有大部分代码是SWFObject 1.5版源码压缩后的COPY.感谢...

    C++中静态成员函数与静态成员变量(static )

    (1)加在局部变量的前面使之成为静态局部变量,作用域还是在函数内部,可是生存周期延长了。 (2)加在全局变量的前面限定该变量作用域为文件作用域,就是说即使其他文件使用了extern扩展作用域也不行。这在C语言的...

    java初学者必看

    7.3 静态域与静态方法 7.3.1 静态域 7.3.2 静态方法 7.3.3 Math类 7.4 构造方法 7.4.1 默认的域初始化 7.4.2 默认构造方法 7.4.3 拷贝构造方法 7.4.4 重载构造方法 7.4.5 调用构造方法 7.4.6 初始化块 ...

    Java入门教程(微学苑)-part1

    3.15 作为方法名来初始化对象 50 3.16 作为参数传递 51 3.17 Java方法重载 52 3.18 Java类的基本运行顺序 53 3.19 Java包装类、拆箱和装箱详解 54 3.20 包装类的应用 54 3.20.1.1 1) 实现 int 和 Integer 的相互转换...

    javaSE代码实例

    15.4.3 匿名内部类的初始化 337 15.4.4 匿名内部类作用的体现 337 15.5 理解内部类 339 15.6 内部接口 340 15.6.1 定义在类中的内部接口 340 15.6.2 定义在接口中的内部接口 341 15.7 小结 342 第16...

    java 异常总结

    当执行一个类的静态初始化程序的过程中,发生了异常时抛出。静态初始化程序是指直接包含于类中的static语句段。 java.lang.IllegalAccessError 违法访问错误。当一个应用试图访问、修改某个类的域(Field)或者调用...

Global site tag (gtag.js) - Google Analytics