package pack0402static;public class MyTestStaticCon {
//请切换1、2处代码
public static final int a = 0;//1、没有进入静态代码块
// public static int a = 0;  //2、进入静态代码块
static {
System.out.println("11111111111");  
}   
}
package pack0402static;public class Test { public static void main(String[] args) {
System.out.println(MyTestStaticCon.a);
}
}
请问代码切换到1处为什么没有执行静态代码块,而代码切换到第二处却执行了静态代码块?java j2se final 初始化

解决方案 »

  1.   

    静态代码块为类在第一次初始化的时候才执行,那么切换到代码1处,在Test的Main中执行MyTestStaticCon.a,结果显示没有执行静态代码块,那么就是类MyTestStaticCon没有进行类的初始化?为啥?
      

  2.   

    LZ反编译下你的Test类即知,如果是字面常量,Test类直接变成了
    public class Test {
     
        public static void main(String[] args) {
            System.out.println(0);//直接使用了常量值
        }
    }
      

  3.   

    因为public static final int a = 0;是一个常量吧?所以Java虚拟机根本没有对MyTestStaticCon类进行初始化。
      

  4.   

    你确定执行结果都一样?不可能吧?看清楚楼主的代码!
    PS:“静态代码块,静态变量都是在类加载的时候执行”可以理解,不过public static final int a = 0;是静态常量,可能根本不需要类的参与。
      

  5.   

    呃,sorry确实看错了!
    多谢楼上指出
      

  6.   

    小生以为楼主是从本类的Main里开始执行的.......
      

  7.   

    其实楼上已经回答了,楼主需要做一些关于JVM的书了,关于虚拟机加载和解释执行的规则与顺序。
    static final是常量,数据存储在常量池中。
    static 变量存放在堆内存,需要初始化类的时候处理。
      

  8.   


    的确这样:
    1=System.out.println(0);
    2=System.out.println(MyTestStaticCon.a);的确这样,可是我们不能模棱两可不求甚解吧?
      

  9.   


    编译器编译的时候直接将MyTestStaticCon.a替换成0了,也就是说Test类与MyTestStaticCon没有任何关系了,执行Test当然不会去加载MyTestStaticCon了
      

  10.   


    我的源码:public class Test {
    // public static final int a = 0;
    public static int a = 0;
    static {
    System.out.println("111111");
    }
     
    public static void main(String[] args) {
    System.out.println(Test.a);
    }
    }
    public class CopyOfTest { public static void main(String[] args) {
    System.out.println(Test.a);
    }
    }
    反编译后的代码:public class Test
    {    public Test()
        {
        }    public static void main(String args[])
        {
            System.out.println(a);
        }    public static int a = 0;    static 
        {
            System.out.println("111111");
        }
    }public class CopyOfTest
    {    public CopyOfTest()
        {
        }    public static void main(String args[])
        {
            System.out.println(Test.a);
        }
    }
    我的反编译怎么和源码差不多??
    没看出来静态的问题。。请教下
    还有我的是jad进行反编译的。jadclipse。
      

  11.   


    ==============================
     public static int a = 0;
     public static final int a = 0;
    这两个是有区别的, public static final int a = 0; 这个是常量,编译时会直接采用常量的字面值。再举例:
    public static final boolean isCode = true;============== 代码中存在这样一段:
    if (isCode) {
      // CODE
    } else {
      // CODE
    }编译器编译后,只会保留
    if (isCode) {
      // CODE
    }
    而else中的代码是不会被编译的,因为JVM已经知道他的结果是什么。
    嘿,不知道这样解释你能否理解一点。
      

  12.   

    static final属性,编译器会解析成对常量的本地copy,该常量存在于引用者的常量池或者字节码流中,
    或者二者都有(参见深入java虚拟机),使用不会引起类的初始化 所以引用静态变量的确和他本身没有任何关系了,就如12楼所说的一样!
      

  13.   


    ============================
    JAD
      

  14.   


    我用的就是JADclipse的。。上面那个就是我反编译的。
    但是没你说的那个。
      

  15.   


    我试了一下 确实是这样 楼主把main中的System.out.println(MyTestStaticCon.a);换成System.out.println(new MyTestStaticCon().a);试一下呢
      

  16.   

    常量,当你用的时候调用就可以了。它一直会存在常量池中。除非线程id失效。static的执行顺序,是JVM这这样规定的。静态先加载,然后是默认块。然后构造。
      

  17.   


    =================
    private static final
    private static
    这两种定义的结果是不一样的。OK。
    你把两种情况都反编译一下。
      

  18.   

    12楼说的很对啊:如果是 public static final int a = 0;//1、没有进入静态代码块  
    在main中的System.out.println(MyTestStaticCon.a); 等价于System.out.println(0);  根本没有类什么屁事
      

  19.   

    这个和JVM的加载机制相关,对于Class来说,通常有三个步骤:
    1. 加载类:如果调用load()方法时,其实内部调用的find()来查找到对应的类;
    2. 解析类:即解析加载的class文件,这时会将类本身的信息和final的信息都放到方法区,也就是有人讲的常量区;此时,final变量本身已经赋值了;相当于调用Class.forName()方法;
    3. 初始化类:调用类初始化方法,默认先调用静态的;
    故,当你执行main时,1,2已经完成,故不会执行;
    但初始化类则是需要调用的;如果想了解得更多更透彻,建议看一下<<深入JVM>>这本书
      

  20.   


    你确定你玩过这个?就来瞎回复?
    我的源码。public class Test {
     private static final int b = 0;
    private static int a = 0;
    static {
    System.out.println("111111");
    }
     
    public static void main(String[] args) {
    System.out.println(Test.a);
    System.out.println(Test.a);
    }
    }
    JAD反编译完:
    public class Test
    {    public Test()
        {
        }    public static void main(String args[])
        {
            System.out.println(a);
            System.out.println(a);
        }    private static final int b = 0;
        private static int a = 0;    static 
        {
            System.out.println("111111");
        }
    }
      

  21.   

    代码:
    public class TestCandidate {
        
        private static final int b = 0;
        
        private static int a = 0;
        static {
            System.out.println("111111");
        }
        
        public static void main(String[] args) {
            System.out.println(TestCandidate.a);
            System.out.println(TestCandidate.b);
        }
    }JAD的反编译结果:
    public class TestCandidate
    {    public TestCandidate()
        {
        }    public static void main(String args[])
        {
            System.out.println(a);
            System.out.println(0);
        }    private static final int b = 0;
        private static int a = 0;    static 
        {
            System.out.println("111111");
        }
    }================================
        private static final int b = 0;
        private static int a = 0;        System.out.println(a);
            System.out.println(0);
    看清楚区别,
    System.out.println(Test.a);        
    System.out.println(Test.a);
    本人是非常不愿意贴代码与调试的,我给你们的只是我的思路与经验,正确与否要靠你们自己在错误中成长。
      

  22.   

    因为在类初始化的时候才执行静态代码块,在深入jvm中写了:在类首次主动使用时进行初始化,主动初始化的一种情况是用到了静态字段,除了final修饰的静态字段外,final被初始化为一个编译时的常量