`
周凡杨
  • 浏览: 235104 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JAVA 静态变量与非静态变量初始化顺序之新解

阅读更多

今天和同事争论一问题,关于静态变量与非静态变量的初始化顺序,谁先谁后,最终想整理出来!
测试代码:

import java.util.Map;

public class T {

	public static T t = new T();
	private Map map = new HashMap();
	public T(){
		System.out.println("Map的值: "+map);
	}
	public static void main(String[] args) {
		 System.out.println(t);
		 System.out.println(t.map);
	}

}

 
运行结果:
Map的值: null
cn.com.algorithm.T@de6ced
{}

为什么Map的值为null,而如果把private static Map map = new HashMap();中的static 去掉,则运行结果为:
Map的值: {}
cn.com.algorithm.T@c17164
{}
所以他觉得非静态变量是在静态变量之前初始化的,这个我太怀疑了,是这样吗?

 

 

 

下面用测试类来证明些实事:

 

public class Demo1 {
    public Demo1(){
    	System.out.println("Demo1的构造函数执行");
    }
}

 

 

public class Demo2 {
	 public Demo2(){
	    	System.out.println("Demo2的构造函数执行");
	 }
}

 

 

 

public class Demo3 {
  public Demo3(){
      System.out.println("Demo3的构造函数执行");
  }
}

 
运行(java -verbose 类名 可以看出来什么时候加载了哪些类):

D:\test>javac TestClassLoaderTime.java
D:\test>java -verbose TestClassLoaderTime > result.txt

result.txt数据片断
[Loaded TestClassLoaderTime from file:/D:/test/] 
[Loaded Demo2 from file:/D:/test/]
Demo2的构造函数执行
--------main方法开始了------------
[Loaded Demo1 from file:/D:/test/]
Demo1的构造函数执行
--------Demo1实例化过------------
[Loaded Demo3 from file:/D:/test/]
Demo3的构造函数执行
--------TestClassLoaderTime实例化过------------
[Loaded java.util.AbstractList$Itr from shared objects file]

 


说明:
1. Demo2 在 Demo1之前被类加载器加载,说明类的静态变量只有在实例化时才去加载
2. Demo3 在 Demo2 之后被类加载器加载,而且Demo3是在类TestClassLoaderTime实例化后才加载的,而Demo2是在main方法执行前被加载,说明静态变量比非静态变量先初始化!

 

 

如果修改测试类为:

public class TestClassLoaderTime {
 
   public TestClassLoaderTime(){
        System.out.println("构造器执行");
   }
   {
         System.out.println("静态代码块执行");
   }
   static Demo2 demo2 = new Demo2();
   Demo3 demo3 = new Demo3();
   public static void main(String[] args) {
          System.out.println("main方法执行");
          new TestClassLoaderTime();
          System.out.println("TestClassLoaderTime实例化过");
    }
}

 
运行结果:

 Demo2的构造函数执行
 main方法执行
 静态代码块执行
 Demo3的构造函数执行
 构造器执行
 TestClassLoaderTime实例化过

 

 说明JAVA中初始化的顺序:
 加载类、 静态成员变量初始化、 静态代码块、非静态成员变量初始化、 构造方法;

 

 

所以对于文章开头的问题,你有自己的答案了吗?

1
7
分享到:
评论
4 楼 周凡杨 2013-01-04  
例子用于理解类的静态变量和非静态变量有点绕了
tianmaotalk 写道
这个问题真的有点绕了,
执行main方法时,jvm发现需要用到T类,且T是第一次被用到,
一、如果t和m都是静态变量
则jvm会顺序初始化 t和map,注意这里是顺序初始化t和map,在t初始化没有完成之前map是不可能被初始化的,这就是为啥map为null的主要原因,当t初始化时,发信T没有非静态成员变量则直接执行构造函数,此时map为null
二、如果t为静态 map为非静态
jvm 只加载t,在初始化t的过程中发现t有一个成员变量则先初始化成员变量再执行构造函数。
此时map已经被初始化。

你写的这个例子用于理解类的静态变量和非静态变量有点绕了,容易把人引入错误方向,建议看think in java里面的例子,简单易懂。

恩 ,其实就是这样,跟我想的一样! 下面的例子确实杂了点
3 楼 tianmaotalk 2012-12-29  
这个问题真的有点绕了,
执行main方法时,jvm发现需要用到T类,且T是第一次被用到,
一、如果t和m都是静态变量
则jvm会顺序初始化 t和map,注意这里是顺序初始化t和map,在t初始化没有完成之前map是不可能被初始化的,这就是为啥map为null的主要原因,当t初始化时,发信T没有非静态成员变量则直接执行构造函数,此时map为null
二、如果t为静态 map为非静态
jvm 只加载t,在初始化t的过程中发现t有一个成员变量则先初始化成员变量再执行构造函数。
此时map已经被初始化。

你写的这个例子用于理解类的静态变量和非静态变量有点绕了,容易把人引入错误方向,建议看think in java里面的例子,简单易懂。
2 楼 w156445045 2012-12-28  
先加载父类的静态变量
再是当前类的静态变量
1 楼 hq369 2012-12-28  
请教一下,什么情况使用静态方法与非静态方法?

相关推荐

    关于Java静态成员变量和静态初始化块等的初始化顺序的详细介绍

    详细介绍了Java的静态成员变量、静态数据块、非静态成员变量和非静态成员变量等初始化顺序

    易语言静态变量初始化

    它们与普通变量的区别在于,静态变量在程序执行期间只初始化一次,并且其值在函数调用之间得以保留。下面将详细解释易语言中静态变量的初始化、作用以及相关示例。 首先,我们要理解静态变量的生命周期。在易语言中...

    java中静态与非静态的变量定义与使用

    总结起来,Java 中的静态变量与非静态变量之间的主要区别在于它们的生命周期、存储位置以及访问方式。静态变量是类级别的,与对象无关,而实例变量是对象级别的,每个对象都有自己的一份副本。理解这两种变量类型...

    java 静态非静态 字段方法 子类父类构造_初始化顺序!

    java 静态_非静态 字段_方法_代码块 子类父类构造_初始化顺序! 三个class 让你清清楚楚 第一个class java代码如下: package initialOrder; class Parent { // 静态变量 public static String p_StaticField...

    java类变量初始化顺序

    详细讲解java类中静态变量,普通标量,对象、基本类型的初始化顺序。

    Java类加载器:静态变量初始化.docx

    在本文中,我们讨论了 Java 类加载器中的静态变量初始化机制,了解了静态变量的初始化顺序和类加载器的生命周期。通过对静态变量初始化机制的理解,我们可以更好地掌握 Java 语言的基础知识,并更好地应用 Java 语言...

    学习java静态数据初始化.doc

    在 Java 中,静态变量的初始化顺序是按照它们在类中的定义顺序进行的。如果一个静态变量依赖于另一个静态变量的值,那么这两个变量的初始化顺序是重要的。 在给定的代码中,我们可以看到有多个静态变量的声明和初始...

    Java静态和非静态成员变量初始化过程解析

    Java静态和非静态成员变量初始化过程解析 Java静态和非静态成员变量初始化过程解析是Java语言中一个非常重要的概念。了解Java静态和非静态成员变量的初始化过程对大家的学习或者工作具有一定的参考学习价值。 首先...

    Java变量初始化

    Java 变量初始化是 Java 语言的基础知识点之一,但也往往被学习者所忽略。 Java 变量初始化的时机是指在 Java 语言中变量的初始化过程,包括变量的声明、初始化和赋值的步骤。 Java 变量声明 在 Java 语言中,每个...

    C++全局变量初始化的一点总结

    初始化顺序方面,同一编译单元内的全局变量按照声明顺序进行初始化,但不同编译单元间的全局变量的初始化顺序是不确定的,这可能导致潜在的问题。如果全局变量之间存在依赖关系,最佳实践是重构代码以消除这种依赖。...

    Java中static静态变量的初始化完全解析

    总的来说,理解Java中静态变量的初始化顺序对于编写可靠的代码非常重要。开发者应避免依赖这种顺序来初始化变量,因为这可能导致难以预料的行为。在编写代码时,推荐的做法是保持静态变量的初始化尽可能简单,避免...

    Java静态初始化块和对象初始化块

    静态初始化块常用于设置类级别的变量,或者执行只应执行一次的初始化操作。例如,如果一个类需要在程序运行前设置一个常量数组,静态初始化块就是合适的选择。 ```java public class InitFiledBlockStatic { ...

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

    特别是当涉及到静态域(静态变量)、非静态域(实例变量)、静态块、非静态块以及构造函数时,明确它们的初始化顺序有助于避免潜在的编程错误。 根据题目提供的内容,我们将重点讨论这些概念以及它们之间的相互关系...

    Java中的静态变量静态方法静态块与静态类.docx

    在静态块中,我们通常进行一些需要进行异常捕获的静态变量的初始化。 例如: ```java public class StaticExample { static { System.out.println("StaticExample static block"); str = "Test"; setCount(2);...

    静态变量与非静态变量获取配置文件application中变量值的区别.docx

    静态变量与非静态变量获取配置文件application中变量值的区别 在 SpringBoot 应用程序中,经常会遇到获取配置文件中的变量值,并将其赋值给变量的情况。在这种情况下,静态变量和非静态变量的使用会出现一些问题。...

    java面试题-类的初始化顺序.doc

    这个顺序表明,无论类之间的继承关系如何,初始化顺序始终是:静态变量和静态初始化块先于非静态成员。在创建对象时,父类的初始化先于子类。这是Java语言规范所规定的,确保在子类访问父类的静态或非静态成员时,...

    java程序初始化顺序

    以下是对Java程序初始化顺序的详细说明: 1. **类加载阶段**: - **加载**:当Java虚拟机(JVM)首次遇到一个类的引用时,会通过类加载器进行加载。加载过程包括找到类的.class文件,读取其字节码,并转化为内存中...

    探究java的ClassLoader及类变量初始化顺序

    总之,深入理解Java的ClassLoader机制和类变量初始化顺序是提升Java编程技能的重要步骤。通过学习这些知识点,开发者可以更好地优化代码、设计更健壮的系统,并解决与类加载和初始化相关的复杂问题。

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

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

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

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

Global site tag (gtag.js) - Google Analytics