请通过SCJP的高手解答,急急急急急急急急急急

时间:2021-02-27 17:47:11
各位网友,大家好:
我做到了一个很奇怪的Java认证考题,始终不解,恳请那位知道的网友帮忙解释一下好吗?
题目是这样的:
What is the output when the user runs "java TestA"?
以下内容为程序代码
--------------------------------------------------------------------------------

public class TestA
{
       TestA()
       {
              System.out.println("P ");
              this.init();
       }
       void init()
       {
            System.out.println("Q ");
       }
       public static void main(String[] args)
       {
              TestB testb=new TestB();
       }
}
class TestB extends TestA
{
      int i=1;
      TestB()
      {
             super();
             System.out.println(i+" ");
      }
      void init()
      {
           System.out.println("C ");
           this.i=2;
           System.out.println(i+" ");
      }
}

--------------------------------------------------------------------------------

A. P Q 1
B. P C 0 2
C. P C 1 1 
D. P C 2 2
E. P C 2 1
F. P Q 0
这道题的正确答案是E.我看这到题目的答案好象是D.可是运行了一遍程序,E答案是正确的。这是为什么呢?想了好半天,始终不解!!!
1.这最后一个1好象是调用了TestB类中的Constructor的super()后,调用了System.out.println(i+" ");的结果,可是实例变量i已被初始化为2,怎么又会边1了呢?
我想关键就是以上这两条,那位知道的网友可以帮我详细的解释一下吗?谢谢了

11 个解决方案

#1


你分析这段程序的时候,注意这几点:
  1.Class TestB的父类Class TestA中,对init()方法进行了重置.
  2.在TestA中申明的是它的子类,那么调用TestB执行时this这个关键子当然就是指向TestB这个类,尽管在TestB的构造器中已经显式的调用了super(),因此首先打印"P".
  3.在TestA中执行this.init()方法时,this实际上是指向TestB类,因此就执行TestB类中重置的init()方法,打印"C".
  4.this.i=2,这句话就是修改TestB类的成员变量i的值,因此System.out.println(i+"");自然就打印2出来.
  5.在回到TestB的构造器去执行System.out.println(i+"")这句话,注意这里应该再次打印出来的是2呀,怎么还是1呀???????????????????????????


  不知你知道这个知识点吗?调用this这个关键字对变量进行操作时就相当于参数值传递,实际上只是在方法内部临时修改变量的值,它操作的只是这个类成员变量的一份拷贝

  这下你该清楚了吧

#2


E是正确答案
你应该看到的是,在MAIN中运行的是TestB,所以你只关心TestB怎么运行的了,首先运行P是没问题的,然后INIT被重载了,输出C好象也没问题。然后是输出2是没问题的,
而I在TESTB中是个“INSTANCE”变量,当跳出INIT后I 就是 1 了啊!

#3


我认为,以上两位的答案均是错误的。
实际上,出现E答案,原因在于实例化一个类时,该类的成员变量init的顺序。在think in java 里面说的很清楚。
1.locate :也就是找到这个类的位置。
2。allocate&static:收集内存,初始化静态成员变量
3。zero:将“INSTANCE”变量置为零或则null;
4.执行父类的构造(输出2是没问题的)
5.init :将“INSTANCE”变量初始化,即将i重新置为1
6。执行本类的构造,故输出得到i=1了

#4


我查了相关的资料,二楼的说法是错误的。城如楼上所说,这与构造器中初始化的顺序有关。

#5


请问楼上所解释的在第5步中提到实例变量重新被初始化,这一步有什么根据?

请注意在类中,对方法的重载(overload)和方法的重置(override)这两者是根本不同的

#6


一个对象建立时候初始化顺序:
1 static and static block的代码部分初始化
2 调用构造器中的super();父类开始初始化
3 当前类的非static 和block初始化
4 构造器其它代码执行
如上:

      void init()
      {
           System.out.println("C ");
           this.i=2;
           System.out.println(i+" ");
      }
i=2后,子类的非static 有初始化,把i = 1
所以E

#7


我发现这个帖子,怎么贴了好几个地方?
而且,正确答案应该已经得到了,楼主怎么还不依不饶啊?

#8


E是正确的,
因为,成员变量i的初始化是在super运行之后进行的,因此,你在init中将i赋值成2,而在super结束之后才执行初始化所以i的值又成了1

#9


在july_typhoon(加油的风)给出的六个步骤中,第四步调用父类的构造函数后,在第六步中调用自身的构造函数中又调用了super(),为什么父类的构造函数只执行了一次,而不是两次??

#10


如果你不调用super()会隐式的调用父类的却省构造函数,如果你显式的使用了super()就不会在调用了,super()主要是用来调用父类的代参构造函数

#11


呵呵,来晚了, and up!

#1


你分析这段程序的时候,注意这几点:
  1.Class TestB的父类Class TestA中,对init()方法进行了重置.
  2.在TestA中申明的是它的子类,那么调用TestB执行时this这个关键子当然就是指向TestB这个类,尽管在TestB的构造器中已经显式的调用了super(),因此首先打印"P".
  3.在TestA中执行this.init()方法时,this实际上是指向TestB类,因此就执行TestB类中重置的init()方法,打印"C".
  4.this.i=2,这句话就是修改TestB类的成员变量i的值,因此System.out.println(i+"");自然就打印2出来.
  5.在回到TestB的构造器去执行System.out.println(i+"")这句话,注意这里应该再次打印出来的是2呀,怎么还是1呀???????????????????????????


  不知你知道这个知识点吗?调用this这个关键字对变量进行操作时就相当于参数值传递,实际上只是在方法内部临时修改变量的值,它操作的只是这个类成员变量的一份拷贝

  这下你该清楚了吧

#2


E是正确答案
你应该看到的是,在MAIN中运行的是TestB,所以你只关心TestB怎么运行的了,首先运行P是没问题的,然后INIT被重载了,输出C好象也没问题。然后是输出2是没问题的,
而I在TESTB中是个“INSTANCE”变量,当跳出INIT后I 就是 1 了啊!

#3


我认为,以上两位的答案均是错误的。
实际上,出现E答案,原因在于实例化一个类时,该类的成员变量init的顺序。在think in java 里面说的很清楚。
1.locate :也就是找到这个类的位置。
2。allocate&static:收集内存,初始化静态成员变量
3。zero:将“INSTANCE”变量置为零或则null;
4.执行父类的构造(输出2是没问题的)
5.init :将“INSTANCE”变量初始化,即将i重新置为1
6。执行本类的构造,故输出得到i=1了

#4


我查了相关的资料,二楼的说法是错误的。城如楼上所说,这与构造器中初始化的顺序有关。

#5


请问楼上所解释的在第5步中提到实例变量重新被初始化,这一步有什么根据?

请注意在类中,对方法的重载(overload)和方法的重置(override)这两者是根本不同的

#6


一个对象建立时候初始化顺序:
1 static and static block的代码部分初始化
2 调用构造器中的super();父类开始初始化
3 当前类的非static 和block初始化
4 构造器其它代码执行
如上:

      void init()
      {
           System.out.println("C ");
           this.i=2;
           System.out.println(i+" ");
      }
i=2后,子类的非static 有初始化,把i = 1
所以E

#7


我发现这个帖子,怎么贴了好几个地方?
而且,正确答案应该已经得到了,楼主怎么还不依不饶啊?

#8


E是正确的,
因为,成员变量i的初始化是在super运行之后进行的,因此,你在init中将i赋值成2,而在super结束之后才执行初始化所以i的值又成了1

#9


在july_typhoon(加油的风)给出的六个步骤中,第四步调用父类的构造函数后,在第六步中调用自身的构造函数中又调用了super(),为什么父类的构造函数只执行了一次,而不是两次??

#10


如果你不调用super()会隐式的调用父类的却省构造函数,如果你显式的使用了super()就不会在调用了,super()主要是用来调用父类的代参构造函数

#11


呵呵,来晚了, and up!