类变量位于.class对象中,只有一份。

解决方案 »

  1.   

    1.初始化cd1->初始化cd2->初始化LoadP(),初始化LoadC()
    2.错
    3.初始化过程:先父类,后子类希望能对楼主有所帮助:)
    我不是高手,呵呵
      

  2.   

    1、实例化原则:对象继承关系的反序进行初始化。结合例子将的话,任何对象的祖宗Object会首先被初始化,然后是LoadP,最后才是LoadC。正如楼主所说的。
      *(将CData视为数据,暂不讨论):对于一个类的初始化(就关注自身),先后是在被调用new的时候,虚拟机总是先分配足够的内存heap空间来容纳类(我个人觉得这个时候应该不能称作“对象”,因为没有实例化)本身所声明的实体变量和它的超类;然后将类的实体变量赋上缺省值;最后才是调用类的初始化子也就是构造里的内容。此外还有一点,static的成员将优先被初始化。
      我将上述的代码的CData和LoadP稍作了改动,变成如下:
    class CData{
       CData(int i ){System.out.println("data is set" + i);}
    }
    abstract class LoadP{
       private CData cd2 = new CData(2);
       static CData cd1 = new CData(1);
       LoadP(){System.out.println("parent construct");}
    }
      运行的结果是:
    data is set1
    data is set2
    parent construct
    child construct
    data is set2
    parent construct
    another child construct
      

  3.   

    3、cd2为父类的私有变量,为什么实例化其子类时,也要为cd2分配内存?
    对!从我上面的运行结果中就能看到。还是验证了一句话,java中每个对象在能够被使用之前都要“安全”——被实例化过的。2、执行实例化时,根据.class 给实例变量分配内存,而不给方法和类变量分配?
    这个显然是不对的。从1的(*)的描述中就能知道变量是肯定会占用空间的。方法也都是要占用空间的。
    “JVM为运行一个程序定义了几种数据区(Data Area),包括:pc寄存器、JVM堆栈、堆、方法区(Method Area)、运行时常量池(Runtime Constant Pool)以及本机方法堆栈(Native Method Stacks)...”,这个可以参见
    http://www.javaresearch.org/article/showarticle.jsp?column=544&thread=112804、如果父类是抽象类,情况变为什么?
    从先向上分析还是会被初始化,这个我不是很清楚了。我猜想应该是还是有所谓的“初始化方法”的,因为从该类的class文件中编译器加入了<init>的。
      

  4.   

    ^_^
    很好的问题....一个类的初始化周期包括装载-->连接-->初始化,当类被首次装入后,JVM规范是需要符合类或接口的主动使用才会初始化类,一切被动的
    使用将不会初始化类或接口...
    一般主动的初始化包括
    1.new 动作实例化一个对象(楼主的行为属于这一类^_^
    2.通过反射操作
    3.调用类的static方法或static字段时
    4.当初始化某个类的子类时
    5.当包含main方法时这些显示的动作将触发类的初始化,当初始化子类时必须先初始化它所有的父类
    但是,接口是不满足要求的,当某个子类的父类是1个接口时是不需要先初始化
    父接口的,只有当这个接口的非final字段首次被使用时才初始化.....
      

  5.   

    也就是说如果楼主第1个例子的父类是个接口的话,并不保证父类先被初始化....
    那么被动使用是什么呢。。?举个例子class AAA {
    static int a = 1111;static{
    System.out.println("init AAA");
    }
    }class BBB extends AAA{
    static {
    System.out.println("init BBB");
    }
    }TEST:
    int i = BBB.a;
    System.out.println(i);
    .................
    结果是
    1111
    init AAA子类BBB并不被初始化.........
    也就是子类必须显示的声明这个静态的非常量字段,而不是在父类声明....
      

  6.   

    fantasyCoder(JC★牛仔) 说得不错!
    但是给出的结果先后反了,应该是:
    init AAA
    1111
      

  7.   

    解释一下这段代码的运行结果吧?呵呵。
    public class Loader2 {
    public static void main(String agrs[]) {
    int i = BBB.a;
    System.out.println(i);
    }
    }interface AAA {
    static int a = 1111;// static{
    // System.out.println("init AAA");
    // }
    // public AAA () {
    // System.out.println(this.getClass().getName());
    // }
    } class BBB implements AAA{
    static {
    System.out.println("init BBB");
    }
    public BBB () {
    System.out.println(this.getClass().getName());
    }
    }结果:
    1111
      

  8.   

    ^_^
    出了小差错...init AAA
    1111
    没错...调用父类的静态变量时将初始化父类,
    我只想说明的是子类在这种情况下
    并不初始化...
      

  9.   

    to gyang(我是谁?) 
    各位,我想问的是实例化中的内存运作,不是初始化.
    ??????????
      

  10.   

    楼主可以在运行的时候用参数:
    java -verbose:class LoadTest
    ......
    [Loaded LoadTest from file:/F:/JavaTest/inside/]
    [Loaded LoadP from file:/F:/JavaTest/inside/]
    [Loaded LoadC from file:/F:/JavaTest/inside/]
    [Loaded CData from file:/F:/JavaTest/inside/]
    data is set
    data is set
    parent construct
    child construct
    [Loaded LoadC2 from file:/F:/JavaTest/inside/]
    data is set
    parent construct
    another child construct
    [Loaded java.lang.Shutdown from shared objects file]
    [Loaded java.lang.Shutdown$Lock from shared objects file]这样装载顺序和静态初始化块的运行一目了然。
    建议看王森写的《Java 深度历险》第二章.
      

  11.   

    takecare(大厅)
    难道实例化就是初始化?????
      

  12.   

    j2nix(八月风清) 
    哪儿有王森写的《Java 深度历险》电子版
      

  13.   

    public class TestInterface
    {
    public static void main(String agrs[])
    {
    int i = BBB.a; //并不载入类BBB
    System.out.println(i); int j = BBB.b; //载入类AAA、BBB,并初始化
    System.out.println(j);
    }
    }interface AAA
    {
    int a = 1111;
    }class BBB implements AAA
    {
    public static int b = 222;  //如果加一个final,则类BBB、接口AAA都不载入 static
    {
    System.out.println("init BBB");
    } public BBB ()
    {
    System.out.println(this.getClass().getName());
    }
    }运行结果:
    ......
    [Loaded TestInterface from file:/F:/JavaTest/inside/]
    1111
    [Loaded AAA from file:/F:/JavaTest/inside/]
    [Loaded BBB from file:/F:/JavaTest/inside/]
    init BBB
    222
    [Loaded java.lang.Shutdown from shared objects file]
    [Loaded java.lang.Shutdown$Lock from shared objects file]
      

  14.   

    gyang(我是谁?) :
    电子版的你在网上找找吧,我这也没有。我在书店买的,正在看呢。
      

  15.   

    另外,反纺译.class文件可以很清楚看到结果:
    Compiled from "TestInterface.java"
    public class TestInterface extends java.lang.Object{
    public TestInterface();
      Code:
       0: aload_0
       1: invokespecial #1; //Method java/lang/Object."<init>":()V
       4: returnpublic static void main(java.lang.String[]);
      Code:
       0: sipush 1111
       3: istore_1
       4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       7: iload_1
       8: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
       11: getstatic #4; //Field BBB.b:I
       14: istore_2
       15: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       18: iload_2
       19: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
       22: return}public final static int b = 222;  //加一个final,则类BBB、接口AAA都不载入
    Compiled from "TestInterface.java"
    public class TestInterface extends java.lang.Object{
    public TestInterface();
      Code:
       0: aload_0
       1: invokespecial #1; //Method java/lang/Object."<init>":()V
       4: returnpublic static void main(java.lang.String[]);
      Code:
       0: sipush 1111
       3: istore_1
       4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       7: iload_1
       8: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
       11: sipush 222
       14: istore_2
       15: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
       18: iload_2
       19: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
       22: return}
      

  16.   

    // 不载入是不可能,只能说是不调用构造方法吧!!
    public class TestInterface
    {
    public static void main(String agrs[])
    {
    int i = BBB.a; //并不载入类BBB
    System.out.println(i); int j = BBB.b; //载入类AAA、BBB,并初始化
    System.out.println(j);
    }
    }interface AAA
    {
    int a = 1111;
    }class BBB implements AAA
    {
    public static int b = 222;  //如果加一个final,则类BBB、接口AAA都不载入
      
                                // 不载入是不可能,只能说是不调用构造方法吧!! static
    {
    System.out.println("init BBB");
    } public BBB ()
    {
    System.out.println(this.getClass().getName());
    }
    }
      

  17.   

    同意 j2nix(八月风清)  的说法。
    接口也会被初始化的,只是没有构造,不会ojbect那样的实例化。to gyang(我是谁?) 
    难道实例化就是初始化?
    当然是啦。
    一般在这种场景下说的“初始化”或者“实例化”已经不只是表面上的构造函数或者赋值语句了。“各位,我想问的是实例化中的内存运作,不是初始化.”
    这个本身就应该是同一个问题吧?或者你能界定一下范围,我们一起来讨论。
      

  18.   

    to  takecare(大厅) 
    我觉得实例化是否是这样一个过程?
    1.装载类(如果原先没有load的话)
    2.为实例变量分配内存(我之所以认为不再为类变量和方法分配内存,是因为类装载时类变量和方法已被分配)
    3.初始化.不知理解是否有误?请指正.
      

  19.   

    fantasyCoder(JC★牛仔)能否仔细讲讲类装载-> 初始化-> 实例化 的概念和具体过程???????????????
      

  20.   

    2、我不赞同,因为我觉得不能把class的装入单独分开,装入也是先将当前用的压入堆栈,在压入父类、超类等,等到栈顶的初始化完成,才轮到当前显式new或者要用的类。这么想主要是因为这样才能确定一个类的对象的大小,要不然怎么定呢?
      

  21.   

    正如你自己说的,当你希望产生1个实例时
    JVM先装载类(如果原先没有load的话)
    这些信息将被保存在JVM开辟的方法区里,
    同时在方法区里开辟内存空间,保存类的一些信息
    final常量将保存在1个叫做常量池的空间里,之后将
    被嵌入到引用它的类的子节码流里....初始化上面已经说的很清楚了....然后实例化操作,类的实例将被保存在堆区....
      

  22.   

    The Java language has three mechanisms dedicated to ensuring proper initialization of objects: instance initializers (also called instance initialization blocks), instance variable initializers, and constructors. (Instance initializers and instance variable initializers collectively are called "initializers.") All three mechanisms result in Java code that is executed automatically when an object is created. When you allocate memory for a new object with the new operator or the newInstance() method of class Class, the Java virtual machine will insure that initialization code is run before you can use the newly-allocated memory. If you design your classes such that initializers and constructors always produce a valid state for newly-created objects, there will be no way for anyone to create and use an object that isn't properly initialized.
      

  23.   

    this指向本类本对象,若无父类对象生成,super指向个啥???????????????????