public class aa
{
aa()
{ this("renqiang");
System.out.println("aa类的第一个构造方法");
}
aa(String s)
{
System.out.println("aa类的第二个构造方法");
}
}
class bb extends aa
{
bb()
{ //super();
this("temp");
System.out.println("bb类的第一个构造方法");
}
bb(String b)
{
System.out.println("bb类的第二个构造方法");
}
public static void main(String args[])
{
bb t=new bb();
}
}/*********************************************************************
我的目的是按照以下的顺序输出如下:
aa类的第二个构造方法 aa类的第一个构造方法 bb类的第二个构造方法 bb类的第一个构造方法但是如果不注释super();的话,则会提示this必须放在constructor的第一句.
让人费解的是.如果注释super();的话,系统还是会默认的会把super()加上来调用
其父类的构造函数的.这样一来,this还不是放在第二句了吗?(即不是放在constructor
的第一句)但是系统此时却又不提示出错了,则正常的运行.如上面所输出的.
哪位能解释的清楚呢?*********************************************************************/
{
aa()
{ this("renqiang");
System.out.println("aa类的第一个构造方法");
}
aa(String s)
{
System.out.println("aa类的第二个构造方法");
}
}
class bb extends aa
{
bb()
{ //super();
this("temp");
System.out.println("bb类的第一个构造方法");
}
bb(String b)
{
System.out.println("bb类的第二个构造方法");
}
public static void main(String args[])
{
bb t=new bb();
}
}/*********************************************************************
我的目的是按照以下的顺序输出如下:
aa类的第二个构造方法 aa类的第一个构造方法 bb类的第二个构造方法 bb类的第一个构造方法但是如果不注释super();的话,则会提示this必须放在constructor的第一句.
让人费解的是.如果注释super();的话,系统还是会默认的会把super()加上来调用
其父类的构造函数的.这样一来,this还不是放在第二句了吗?(即不是放在constructor
的第一句)但是系统此时却又不提示出错了,则正常的运行.如上面所输出的.
哪位能解释的清楚呢?*********************************************************************/
{
bb()
{ this("temp");
System.out.println("bb类的第一个构造方法");
}
bb(String b)
{super();
System.out.println("bb类的第二个构造方法");
}
public static void main(String args[])
{
bb t=new bb();
}
}
maquan('ma:kju) ( ) 信誉:100 Blog 加为好友 2007-4-14 21:48:42 得分: 0
编译的时候“提示this必须放在constructor的第一句”的目的在于,子类在构造过程中,如果要引用另一个构造方法,必须在“其它执行语句”的前面。而这里的“其它执行语句”,指的是子类里写的某些语句,不包括“父类里的语句”。事实上,父类的构造方法*一定*是要被首先调用的(无论是隐式的还是显式的)。这正是 Java 语法“严格”的表现,基本上可以说,你找不到它“不恰当”的地方 ;)
您所说的:"而这里的“其它执行语句”,指的是子类里写的某些语句,不包括“父类里的语句”。"虽然super();是父类的语句,但是如果说把我上面程序的//super()注释去掉,则不能编译,
说this必须在第一行.
还有你可能没有明白我的意思,如果把//super()加上注释的话,也就是说java也会首先执行super()再执行this这样程序会正常的编译运行.但是此时this不是相当于放在了第二句了吗?虽然super()是隐式执行的.
只要aa或bb类的源码中定义了构造方法,且构造方法的第一条语句
不是“this(可选参数)”或“super(可选参数)”调用,
编译器都会默认产生一条super()语句,作为这个构造方法的第一条语句。这样做的目的就是保证初始化子类前,所有父类都已正确初始化。因为你是通过bb t=new bb()开始的,
所以先调用bb()构造方法,因bb()构造方法第一条语句是this("temp");
所以编译器不会为bb()构造方法产生super()语句,JVM接着不会调用
aa类的构造方法,而是转到bb(String b),因bb(String b)内部第一条
语句不是“this(可选参数)”或“super(可选参数)”调用,所以编译器
已为它产生了一条super()语句,JVM接着调用aa(),再到aa(String s),
再到java.lang.Object的Object()调用结束。
所以结果就是:aa类的第二个构造方法
aa类的第一个构造方法
bb类的第二个构造方法
bb类的第一个构造方法另外“this(可选参数)”或“super(可选参数)”语句只能出现在最前面,
只能二选一,这是语言规范,没什么好解释的。
有不明白的地方用javap -verbose bb看看字节码或者看看javac的源码
在com.sun.tools.javac.comp.MemberEnter类有点说明
但是您所说的:"因bb(String b)内部第一条
语句不是“this(可选参数)”或“super(可选参数)”调用,所以编译器
已为它产生了一条super()语句"如果这样的话,在产生了一条super()语句之后
那么他后面的语句就不执行了吗?也就是说bb(String b)内还有这样一句话:"System.out.println("bb类的第二个构造方法");".如果不是的话,而且照你所说的流程的话.输出的第一句话应该是:"bb类的第二个构造方法"才对啊?
===============================
执行。相当于是
bb(String b) {
super();
System.out.println("bb类的第二个构造方法");
}用javap -verbose bb查看反编译后的代码也跟上面类似:
bb(java.lang.String);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: invokespecial #6; //Method aa."<init>":()V //这里就当相于super()
4: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #7; //String bb类的第二个构造方法
9: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V //这里就当相于System.out.println("...")
12: return
=================================================
不对。调用super()就相当于调用
aa() {
this("renqiang");
System.out.println("aa类的第一个构造方法");
}
但是每个子类的构造方法中剩余的代码还是要继续执行的,你可以想象一下递归调用的流程。好了,就聊这么多,太多细节还得说编译流程,各类JVM指令。