最近在总结一些自己以前学JAVA的东西,这次搞的是初始化的问题。先不说问题,大家先看
下面2个类:package initial;public class AmazingCls {
        //final static double a = Math.random();
final static int a = 18;
static{
System.out.println("-----static---------");
}

public AmazingCls(){
System.out.println("------对象被创建---");
}

public static void main(String[] args){
// int b = AmazingCls.a;
System.out.println("------main()--------");
}
}
package initial;public class AmazingTest { public static void main(String[] args) { //new AmazingCls();
//int b = AmazingCls.a;
System.out.println("------main()--------"); }}运行第一个例子(注释那句去掉与否不影响输出效果),输出:
-----static---------
------main()--------运行第二个例子,输出:
------main()--------
加上int b = AmazingCls.a;这句,输出还是:
------main()--------
再加上new AmazingCls();这句,输出:
-----static---------
------对象被创建---
------main()--------好了看到这里我的问题是什么呢?相信高手已经知道了,这就是主动调用与被动调用的问题
到底那些情况是主动调用?
哪些是被动调用呢?
我发此贴的目的就是与大家探讨下这个问题我现在的总结是:
用new生成对象就是对此类的主动调用;直接运行有main()的类也是对此类的主动调用;
类的成员变量在执行期间才能得到值的,访问此成员也可是对此类的主动调用。比如:final static double a = Math.random();
那么被动调用都是哪些情况呢?大家一起帮忙总结下,不吝赐教~~~~~~感谢~~~~~~

解决方案 »

  1.   

    这个结果倒真是amazing了,我以为static{}总会调用的,为什么在第二个类运行的时候结果是那样的呢?
      

  2.   

    哦,原来跟final有关,如果你把final去掉,结果会不一样
    难道是对常量的访问并不需要static初始化?估计是的。学习下去
      

  3.   

    类初始化为主动调用,static语句块为被动调用
      

  4.   

    加上int b = AmazingCls.a;这句,输出还是:
    ------main()-------- 我说的是这个
      

  5.   

    类的成员变量在执行期间才能得到值的,访问此成员也可是对此类的主动调用。比如:final static double a = Math.random(); 学习
      

  6.   


    说的很模糊啊类肯定要初始化的,jvm调用前,在类装载的时候必须初始化,初始化时static{}要执行的。
      

  7.   

    这是一个类初始化问题,类被调用要经过 装载——连接——初始化;而初始化经常是一个延迟的操作,虚拟机规范规定,当一个类型第一次被主动调用时,类型必须被初始化,初始化的时候会执行类型初始化语句。
    当类型进行以下操作时被认为是类型主动调用,类型必须初始化。
    当创建一个类的实例时(无论是new还是反射,克隆,反序列化等等)。
    当调用某个类的静态方法时。
    当调用某个类的静态字段或者给其赋值时(此处必须是类自身定义的字段,不能为父类字段,而且不能为常量,常量不被认为是类的成员字段)
    当调用api的某些反射方法对类型进行访问时
    当初始化这个类型的子类时
    当这个类是程序入口时,即程序启动是通过这个类中的main方法时。
      

  8.   

    当调用某个类的静态字段或者给其赋值时(此处必须是类自身定义的字段,不能为父类字段,而且不能为常量,常量不被认为是类的成员字段) 
    这个,解决了我的部分疑问
    那当
    final static double a = Math.random();
    这样定义时,结果又是不一样的,怎么解释呢?
    a不是常量?
    或者运行期确定值的也是主动调用?
      

  9.   

    final static double a = Math.random();这个东西不是常量,虽然它与final static double a = 3;这种语句看起来很像,但是实际上前者不是常量,而后者是常量,这跟java编译器有关。
      

  10.   

    在java中,并不是static加上final的组合修饰,那个字段就会是常量。
      

  11.   

    常量分为两种:运行时常量和编译时常量static final int a = 3; // 编译时常量,编译器在编译时会将所有用到该变量的地方替换成相应的字面值
    static final int a = (int)Math.random(); // 运行时常量,在运行的时候才能确定知道这个之后,问题就迎刃而解了,
    因为你的final static int a = 18;
    是编译时常量,所以int b = AmazingCls.a;
    会被编译成int b = 3,这样就不会涉及到类AmazingCls的装载,也就不会调用这个类的static 块了。
    对于final static double a = Math.random(); 
    是运行时常量,必须装载类之后才能够得到值。下面我给出一个例子:public class Client 
    {
    static final int a = 3;

    static {
    System.out.println("static block");
    }

    public Client() {
    System.out.println("Client initialize!");
    }

    public static void main(String[] args) {

    System.out.println("Client main");
    }
    }class Other {
     public static void main(String[] args) {
     int b = Client.a;
     System.out.println("other main");
     }
    }类Other编译后的class文件内容为:
    class com.ibm.datatools.we.test.Other {
      
      // Method descriptor #6 ()V
      // Stack: 1, Locals: 1
      Other();
        0  aload_0 [this]
        1  invokespecial java.lang.Object() [8]
        4  return
          Line numbers:
            [pc: 0, line: 51]
          Local variable table:
            [pc: 0, pc: 5] local: this index: 0 type: com.ibm.datatools.we.test.Other
      
      // Method descriptor #15 ([Ljava/lang/String;)V
      // Stack: 2, Locals: 2
      public static void main(java.lang.String[] args);
         0  iconst_3
         1  istore_1 [b]
         2  getstatic java.lang.System.out : java.io.PrintStream [16]
         5  ldc <String "other main"> [22]
         7  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
        10  return
          Line numbers:
            [pc: 0, line: 53]
            [pc: 2, line: 55]
            [pc: 10, line: 56]
          Local variable table:
            [pc: 0, pc: 11] local: args index: 0 type: java.lang.String[]
            [pc: 2, pc: 11] local: b index: 1 type: int
    }
    看到没有,那个地方被替换成3了。
      

  12.   

    主动调用被动调用这种说法不太听说过。
    看了以上的回帖,问题集中在final上。
    下面是我的理解:
    如果是:
    final static double a = 3;//Math.random();
    则编译的时候将a作为常量。
    当你调用double b = AmazingCls.a;
    可以直接得到值是3.如果你去掉了final,则这个值就要在运行时候再计算。
    则要加载AmazingCls类,所以才会打印出static块的内容。如果是:
    final static double a = Math.random();
    不管是否有final,a不会是编译时候可以得到的值。
    所以必须要去运行时计算,
    则要加载AmazingCls类,所以才会打印出static块的内容。
      

  13.   

    使用final不需要加载类!
    否者要加载类!
    类一加载-static 调用
      

  14.   

    常量分编译期常量和运行期常量
    final static double a = Math.random(); 
    这个是运行期常量,只有在程序运行时才能出结果
    final static double a = 3;
    这个是编译期常量
      

  15.   

    public static Class<?> forName(String name,
                                   boolean initialize,
                                   ClassLoader loader)
                            throws ClassNotFoundException
    The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.