package com.ynyee.test;class ZZ {
private final int a;
// !public static final int b;
public final static int b = 1;private int c = 10;
private Integer d = new Integer(11);public ZZ() {
// TODO Auto-generated constructor stub
System.out.println(this);
this.a = 0;
int a = this.c;
System.out.println(a);
System.out.println(this.d);
// !b =0;
}
}public class CC {
public CC() {
System.out.println(this + " " + "77");
System.out.println("CC Constract start.");
this.show();
System.out.println("CC Constract end..");
}void show() {
System.out.println("CC.show()");
}public static void main(String[] args) {
// new ZZ();
new BSon();
}
}abstract class BB extends CC {
private int a = 88;public BB() {
System.out.println(this + " " + a);
System.out.println("BB Constract start.");
this.show();
System.out.println("BB Constract end..");
}abstract void show();
}class BSon extends BB {
{
System.out.println(this + "_1");
}
private int a = 2;public BSon() {
System.out.println(this.a);
this.show();
}void show() {
System.out.println("BSon.show()" + a);
}
}
运行上述的程序,控制台将会输出什么?你回答了答案再去运行看看结果,请解释这个结果的原因。回答这个问题,能让你了解创建一个对象的流程。似乎NEW一个对象分为3个步骤,将引用指向一块堆内存,然后就有地址了,也就是可以操纵内存了,可以在内存中构建这个对象了。因为刚刚指引了一块内存地址,其他的事情还都没做,所以定义的所有的成员变量为初始值(基本数据类型为),然后停下该类所有的事情用自身这个对象来构造他的父类,如果父类中还有父类,就跳过当前父类的操作跳到更上一曾,在构造父类之前,向自身包含的父类成员进行赋值,并且执行匿名方法,匿名方法和成员变量的赋值的顺序是编写代码的时候的先后顺序,执行完匿名方法,就执行构造函数(父类中的),父类中的构造完成,再通过自身对象接口给成员变量赋值,然后通过自身对象接口执行完自身的匿名方法,然后运行自身的构造函数。
以上纯属个人观点,高手见笑了。如有理解错误请指点。

解决方案 »

  1.   


    关于show()这个方法的调用,没想到结果~lz说的匿名方法指的是什么??
      

  2.   

    就是在一个类中
    class C{
        {
          System.out.println("ssssssss");
        }
        public C{
          
        }{
          System.out.println("aaaaaaaa");
        }
    }
    无论前后匿名方法都在构造前执行
      

  3.   

    关于匿名方法。可以执行这段代码看效果
    package com.ynyee.test;public class Test3 { /**
     * @param args
     */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    C.class.toString(); System.out.println("------------------");
    new C();
    }}class C { public C() {
    System.out.println("执行构造");
    } static {
    System.out.println("静态匿名方法..");
    } {
    System.out.println("动态匿名方法..");
    }
    }
      

  4.   

    其实java在生成对象的时候不是你们想像的那么做的,java在生成对象的时候先向内存申请空间,然后产生对这个空间的指针,然后把这个指针转换成java的句柄。然后执行构造函数,这个构造函数其实就是子类中的构造函数,只不过构造函数第一句会调用super()来执行父类构造函数而已,所以看起来是先执行了父类的构造函数,其实不然。(也许有些人会说第一句没有写super()这一句,其实没有写并不代表没有,如果没有写super(),编译器会自动加上无参数的super(),如果你的父类没有无参数构造函数,如果你第一句不写super(....)那么就不能通过编译),在这,其实构造函数本身其实就是一个返回void的普通方法,方法的实际名称为public void <init>()构造函数并不负责产生对象,它只是一个普通方法,区别只是生产对象后立即执行且不能被对象自身显示调用而已,如果运用native技术,可以绕过构造方法建立对象并且还可以在不建立对象的情况下执行构造方法。
    至于楼主所说的匿名方法,其实这个说法并不正确,正确的说法应该是叫对象初始化块,这些块与构造方法一样在对象生成后立即执行,而且它会在构造方法之前执行,只不过这种初始化块没什么作用,一般初始化工作都在构造方法内完成。
      

  5.   

    然后执行构造函数,这个构造函数其实就是子类中的构造函数,只不过构造函数第一句会调用super()来执行父类构造函数而已,
    如果父类的构造是隐含的在子类的构造中调用的,你这么说也就是说是子类的构造触发了父类的构造,如果按你的理论来理解,那么子类中的成员变量在执行构造前已经进行了赋值操作,如果没有进行赋值,则引用类型指向NULL,基本数据类型为0,如果在定义的时候直接对成员进行了赋值,那么按你的说法,此时定义时赋值的成员变量应该已经不为初始值了,但是事实这些定义时赋值的成员变量仍然是0或者指向NULL,这个结果让我对子类的构造隐含调用父类这个过程产生质疑。我认为父类的构造不是子类的构造触发的,在父类构造和子类构造之间,应该还最少有一个阶段,就是给子类中的成员变量赋值和进行你所说的“对象初始化块”,而且这个对象初始化块的名字不是很符合实际的应用,这两个大括号之间功能和一个没有名称没有参数的方法具有同样的功能。上述代码进行稍作修改就可以测试我的这个结论
      

  6.   

    http://blog.csdn.net/ZangXT/archive/2008/10/31/3196244.aspx
      

  7.   

    回楼主的疑问,其实很多时候java代码在语法上存在欺骗性,它很多时候欺骗了编写者对java程序的真实执行过程,或许java的设计者就是希望编码这这样去认为的,但是实情却与里面表面的理解截然不同,当我们执行new Clazz()这样的操作,他的底层倒是怎么操作的?
    首先是执行new关键字来向内存申请空间,然后执行子类构造方法,子类构造方法调用父类构造方法,然后再给成员变量赋值(对默认赋值的成员变量),再执行初始化块,再执行构造函数内语句(这些语句可能是在构造函数内给成员变量赋值的)。你那所谓匿名方法,其实根本就不是一个方法,只是初始化块而已,他只是会在构造函数前成员变量赋值后执行而已。
    你就不要跟我争论你对java语言自己异想天开的理解了,因为java字节码命令就是这么执行的。
      

  8.   

    在java中,所有的方法都是有方法签名的,所有的属性也有属性签名(如果你层进行过jni开发你就会知道方法签名的)。但是那个你所谓的匿名方法根本就没有什么方法签名,它只是在构造方法前端执行而已,它们不可能像真正的方法那样通过特殊手段把它们挖出来。