http://www.huihoo.org/rt/rtj/rtj_rta.html

解决方案 »

  1.   

    t3.t3 == t3.t3.t3 == t3.t3.t3.t3……  是地址相等的,在内存中实际上t3.t3应该写成
    TT3.t3(如果你使用Eclipse,它会告诉你上面的写法可能有问题,应该改成静态访问方式即,T3.t3)
      

  2.   

    谢谢 ChDw(米)的回答,我注意到了是这么回事。
      

  3.   

    这个问题。。其实很简单啊。。俺简单说说一个类被虚拟机使用的时候,静态变量是如何处理的。时间久了,有些地方可能记错了,要见谅。
    一个java通过(1)装载(2)连接(3)初始化这三个步骤之后才能被虚拟机使用。在连接过程中,会有一个解析的过程,这个过程会在类型的常量池中寻找类、接口、字段和方法的符号引用。但是俺们主要关注的是“初始化”这个阶段。
    初始化,其实工作就是为类常量赋予正确的初始值。在俺们的Java代码中,一个正确的初始值通过类变量初始化语句或者静态初始化语句来完成的。这里参照下楼主的例子1:
    static public TT3 t3 = new TT3(23);
    就是这句,它实际上等价于:
    static public TT3 t3;
    static {
        t3 = new TT3(23);
    }
    这些类变量的初始化语句和静态初始化static{}都会被java编译器收集,放到一个特殊的方法中。
    这个方法叫做“类初始化方法”或者“接口初始化方法”(针对类和接口的叫法不同)。在class文件中,俺们可以看到这个方法名字叫“<clinit>”,需要说明的是,这个方法是java程序无法调用的,只有虚拟机才能够调用,用来为其设置正确的初始值。
    俺们看看楼主例子1的class文件:
    <<
    Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   aload_0
       5:   iload_1
       6:   putfield        #2; //Field i:I
       9:   return
    static {};
      Code:
       0:   new     #3; //class TT3
       3:   dup
       4:   bipush  23
       6:   invokespecial   #4; //Method "<init>":(I)V
       9:   putstatic       #6; //Field t3:LTT3;
       12:  return
    >>
    这段就是java编译器生成的<clinit>方法了。这个初始化方法只会在类第一次被装载的时候由虚拟机执行,并放入方法区中。
    所以,例子1中static public TT3 t3 = new TT3(23)只被执行了一次而已,无论多少个t3,都是第一次初始化时的那个地址,所以输出的结果一定是23。这里和递归没有关系。