`

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

阅读更多

注意,有一点很有意思,当使用“.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 编程语言中,类的初始化顺序对于理解程序的行为至关重要。特别是当涉及到静态域(静态变量)、非静态域(实例变量)、静态块...

    java的静态域实例域

    1. 类的静态域在类加载时按它们在代码中的顺序进行初始化。 2. 当创建新对象时,首先执行构造方法。在构造方法内部,实例域按照它们在代码中的顺序初始化。 理解这些基本概念对于编写正确的Java代码至关重要。静态...

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

    首先,静态数据成员通常在类声明中被声明,然后在包含类方法实现的源文件中进行初始化。例如: ```cpp class Test { public: static int num; }; int Test::num = 0; ``` 在这个例子中,`Test`类有一个静态成员`...

    Java中初始化数据域的四种方法

    静态初始化块只在类加载时执行一次,用于初始化静态字段。虽然这个例子中没有给出具体的代码,但可以想象如下情况: ```java public class InitFiled { private static List<String> list; static { list = ...

    易语言静态变量初始化源码.zip

    在这个“易语言静态变量初始化源码.zip”压缩包中,我们可以预见到它包含了一个或多个示例程序,这些程序主要展示了如何在易语言中使用静态变量进行初始化。 在编程中,变量是存储数据的容器,而静态变量有别于普通...

    Java初始化顺序1

    多个类加载的时候,不是依次初始化好每个类的静态数据,再初始化每个类的实例成员,而是初始化好第一个类的静态数据,实例变量,再初始化下一个类的静态数据,实例变量。 static 关键字不能应用于局部变量,因此它...

    .NET :静态类的理解

    然而,静态类可以有一个静态构造函数,这个构造函数在类首次被使用时调用,通常用于初始化静态字段。 使用静态类的一个主要优点是它们在内存中位于栈上,而不是堆上,这通常导致更快的访问速度和更小的内存开销。...

    类的static,const,static const,const static成员的初始化

    * 初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员。 3. 类里的 static const 和 const static 成员初始化 在学习 static 成员初始化时,我们发现了网上有很多关于 ...

    java初始化和清理

    Java类是在需要使用时,比如创建对象、访问静态域或静态方法时,才会被加载。这种方式称为按需加载,意味着类的加载是延迟的,从而提高了程序启动的速度和内存的使用效率。这种加载方式主要得益于Java虚拟机(JVM)...

    Java实例域初始化方法及顺序

    "Java实例域初始化方法及顺序" Java实例域初始化是Java编程语言中的一种初始化方式,用于初始化Java实例域的值。在这篇文章中,我们将详细介绍Java实例域初始化的方法和顺序,通过示例代码,介绍了Java实例域初始化...

    Java类加载连接和初始化原理解析

    * 当访问一个静态域时,只有真正声明这个域的类才会被初始化 * 当通过子类引用父类的静态变量,不会导致子类初始化 * 通过数组定义类引用,不会触发此类的初始化 Java类加载连接和初始化原理分析是Java虚拟机中一个...

    C++类中的静态成员变量和静态成员函数的作用

    // 在类外部定义并初始化 ``` **2. 访问** - **类名访问**: 静态成员变量可以通过类名直接访问,而不需要创建对象。 ```cpp MyClass::count++; // 直接通过类名访问静态成员变量 ``` - **对象访问**: 尽管...

    C语言初始化效率问题以及关键字解释

    ### C语言初始化效率问题及关键字解析 #### 一、初始化效率 **静态变量初始化** 在C语言中,静态变量的初始化具有很高的效率。这是因为当可执行文件被加载到内存时,静态变量的初始值就已经被放置在其对应的内存...

    数据结构单链表初始化c/c++语言代码实现

    1. 静态初始化:在C++中,可以通过静态初始化创建一个空链表,即在声明时就指定头节点的`next`为`nullptr`。这通常用于声明全局变量或静态局部变量: ```cpp ListNode head = {0, nullptr}; // C++11及以后版本 ...

    面向对象c++静态成员的使用

    // 初始化静态数据成员 int main() { point p1(3); p1.show(); point p2(6); p2.show(); point p3(8); p3.show(); return 0; } ``` #### 详解 1. **静态数据成员**: - 在`point`类中,`int count`被...

    ARM的C语言运行环境初始化研究

    综上所述,本文详细介绍了在ADS1.2集成开发环境下,ARM C语言程序的运行环境初始化过程,特别是针对全局变量初始化和变量存储空间分配的具体实现方法。这对于从事嵌入式系统开发的工程师来说,是一篇非常有价值的...

    PHP中的静态变量及static静态变量使用详解

    在这个例子中,MyStaticInit方法起到了类似静态构造器的作用,用来初始化静态变量。 总结来说,静态变量在PHP中是一种特殊类型的变量,它们在函数或类中被频繁使用,有助于程序员管理数据和状态。静态变量对于缓存...

    易语言源码实现易语言类静态数据成员的方法.rar

    3. **生命周期**:静态数据成员在类加载时被初始化,直到程序结束才释放,具有全局作用域和生命周期。 实现易语言类静态数据成员的方法: 1. **声明**:在类定义内部,使用`静态`关键字声明静态数据成员。例如: `...

Global site tag (gtag.js) - Google Analytics