黑马程序员技术交流社区

标题: 大神给解释下这道程序的运行结果 [打印本页]

作者: kimi    时间: 2013-5-26 12:09
标题: 大神给解释下这道程序的运行结果
本帖最后由 kimi 于 2013-5-31 01:11 编辑
  1. class Person
  2. {
  3.         public Person(){
  4.                 this.print();
  5.         }
  6.         public void print(){}
  7. }
  8. class Student extends Person
  9. {
  10.         private int score=90;
  11.         public Student(int score){
  12.                 this.score = score;
  13.         }
  14.         public void print(){
  15.                 System.out.println("score="+this.score);
  16.         }
  17. }
  18. public class Test
  19. {
  20.         public static void main(String[] args){
  21.                 Student stu = new Student(98);
  22.         }
  23. }
复制代码
运行结果是0,这是为嘛啊
作者: 江南雨    时间: 2013-5-26 12:38
呵呵,我也是菜鸟。。确实好奇怪,我认什么都没有输出
作者: 画饼    时间: 2013-5-26 12:45
stu.print(); 调用方法,就可以打印出,你要的数字
作者: 画饼    时间: 2013-5-26 12:51
说Student继承了父类的构造方法。或者有一个父类的对象。在new Student的时候,你打印出来的值。是父类那个构造方法的prin。应该是先在Student对象里面创建了一个父类对象。或者先调用了父类的构造方法,而prin方法被你重写了的原因。。个人猜测。基础不牢。各位勿喷。
作者: 喜欢流浪    时间: 2013-5-26 13:50
  1. class Person
  2. {
  3.         public Person(){
  4.                 this.print();
  5.         }
  6.         public void print(){}
  7. }
  8. class Student extends Person
  9. {
  10.                 private int score=90;
  11.         public  Student(int score ){
  12.               this.score = score;
  13.                           System.out.println("score="+this.score);
  14.         }
  15.         public void print(){
  16.                System.out.println("score="+this.score);
  17.         }
  18. }
  19. public class Test
  20. {
  21.         public static void main(String[] args){
  22.                 Student stu = new Student(98);
  23.         }
  24. }
复制代码
楼主在 Student() 下 插入一句System.out.println("score="+this.score);
你在看结果  
score=0
score=98
先打印的是score= 0  在结合楼上解释,你肯定会更明白的!你打印的是重写之后的父,也就是Person()下print,当然为0 了
作者: 王靖远    时间: 2013-5-26 14:35
画饼 发表于 2013-5-26 12:51
说Student继承了父类的构造方法。或者有一个父类的对象。在new Student的时候,你打印出来的值。是父类那个 ...

正解。new的对象还没有调用方法。打印的0是new对象时调用父类构造函数打印出来的。
作者: 江南雨    时间: 2013-5-26 15:10
画饼 发表于 2013-5-26 12:51
说Student继承了父类的构造方法。或者有一个父类的对象。在new Student的时候,你打印出来的值。是父类那个 ...


其实我想问一下的是,创建子类的对象时是会执行父类的构造方法,即会创建父类的对象,那构造方法(person构造方法)里面的this代表的是student的一个对象还是person的一个对象?
作者: 江南雨    时间: 2013-5-26 15:13
王靖远 发表于 2013-5-26 14:35
正解。new的对象还没有调用方法。打印的0是new对象时调用父类构造函数打印出来的。 ...

new的对象还没有调用方法,你指的方法是?
作者: 王靖远    时间: 2013-5-26 15:20
江南雨 发表于 2013-5-26 15:13
new的对象还没有调用方法,你指的方法是?

指的是,子类复写的print方法。
作者: First    时间: 2013-5-26 15:24
本帖最后由 First 于 2013-5-26 15:28 编辑
  1. 这是一个对象的初始化问题。

  2. class A {
  3.         static int a1 = 1;
  4.         int a2 = 2;
  5.         
  6.         A(){
  7.                 System.out.println("基类A的构造函数:init A");
  8.                 System.out.println();
  9.         }
  10.         static {
  11.                 a1 = 10;
  12.                 System.out.println("基类A的静态代码块:static block a1 = " + a1);
  13.         }
  14.         
  15.         {
  16.                 a2 = 20;
  17.                 System.out.println("基类A的代码块:block a2 = " + a2);
  18.         }
  19.         
  20.         static void showA(){
  21.                 System.out.println("static showA = " + a1);
  22.         }
  23.         
  24.         
  25. }

  26. class B extends A{
  27.         
  28.         static int b1 = getB1();
  29.         int b2 = getB2();
  30.         
  31.         B(){
  32.                 System.out.println("父类B的构造函数:init B");
  33.                 System.out.println();
  34.         }
  35.         
  36.         static {
  37.                 b1 = 110;
  38.                 System.out.println("父类B的静态代码块:static block b1 = " + b1);
  39.         }
  40.         
  41.         {
  42.                 b2 = 220;
  43.                 System.out.println("父类B的代码块:block b2 = " + b2);
  44.         }
  45.         
  46.         static void showB(){
  47.                 System.out.println("static showB = " + b1);
  48.         }
  49.         
  50.         static int getB1(){
  51.                 System.out.println("父类B的静态成员初始化赋值函数:static getB1");
  52.                 return 11;
  53.         }
  54.         
  55.         int getB2(){
  56.                 System.out.println("父类B的成员初始化赋值函数:getB2");
  57.                 return 22;
  58.         }
  59. }

  60. class C extends B{
  61.         
  62.         static int c1 = getC1();
  63.         int c2 = getC2();
  64.         
  65.         C(){
  66.                 System.out.println("子类C的构造函数:init C");
  67.         }
  68.         
  69.         static {
  70.                 c1 = 1110;
  71.                 System.out.println("子类C的静态代码块:static block c1 = " + c1);
  72.                 System.out.println();
  73.         }
  74.         
  75.         {
  76.                 c2 = 2220;
  77.                 System.out.println("子类C的代码块:block c2 = " + c2);
  78.         }
  79.         
  80.         static void showC(){
  81.                 System.out.println("static showC = " + c1);
  82.         }
  83.         
  84.         static int getC1(){
  85.                 System.out.println("子类C的静态成员初始化函数:static getC1");
  86.                 return 111;
  87.         }
  88.         
  89.         int getC2(){
  90.                 System.out.println("子类C的成员初始化函数:getC2");
  91.                 return 222;
  92.         }
  93.         
  94. }

  95. public class Demo
  96. {
  97.         public static void main (String[] args){
  98.         C c = new C();
  99.         }
  100. }

  101. /* 输出结果:
  102. 基类A的静态代码块:static block a1 = 10
  103. 父类B的静态成员初始化赋值函数:static getB1
  104. 父类B的静态代码块:static block b1 = 110
  105. 子类C的静态成员初始化函数:static getC1
  106. 子类C的静态代码块:static block c1 = 1110

  107. 基类A的代码块:block a2 = 20
  108. 基类A的构造函数:init A

  109. 父类B的成员初始化赋值函数:getB2
  110. 父类B的代码块:block b2 = 220
  111. 父类B的构造函数:init B

  112. 子类C的成员初始化函数:getC2
  113. 子类C的代码块:block c2 = 2220
  114. 子类C的构造函数:init C


  115. //**************
  116. * 结论:
  117. * 静态成员函数-->静态成员变量-->静态代码块
  118. *
  119. * 成员函数-->成员变量-->代码块-->构造函数
  120. *
  121. * 因为成员变量是在赋值之前开辟的并被赋值为默认值 0,false,null;
  122. *
  123. * 因此对象初始化顺序为:
  124. * 1.为成员变量开辟空间并赋值为默认值
  125. * 2.调用构造函数(为执行方法体)
  126. * 3.调用父类构造函数
  127. * 4.给成员变量赋初始值
  128. * 5.执行代码块
  129. * 6.执行构造函数方法体。
  130. *
  131. * 因此你的函数出现0的情况是因为
  132. * 步骤1 执行后 score = 0;
  133. * 步骤3 执行时 score = 0;并被打印了;
  134. * 步骤4 执行时 socre = 90; 才会执行。
  135. *
  136. */
复制代码

作者: 萌小子    时间: 2013-5-26 15:26
你运行下这段代码就知道运行顺序了
创建子类对象时,默认先调用父类的无惨构造方法,如果父类构造方法只有有参的,子类必须使用super调用父类构造方法。像这个例子,父类和子类都有静态代码块,创建子类对象时,先调用父类的静态代码块,其次调用子类的静态代码块,然后父类的构造方法,最后子类的构造方法。
  1. class P {         
  2.     static{
  3.         System.out.println("代码块P");
  4.     }     
  5.     P(){
  6.         System.out.println("构造方法p");
  7.     }     
  8. }
  9. public class C extends  P{     
  10.     static{
  11.         System.out.println("代码块C");         
  12.     }     
  13.     C(){
  14.         System.out.println("构造方法c");
  15.     }     
  16.     public static void main(String[] args) {
  17.         new C();
  18.     }
  19. }
复制代码
运行结果:
代码块P
代码块C
构造方法p
构造方法c

作者: zjd    时间: 2013-5-26 15:27
不要忘记子类中的构造函数有一个隐藏的super();语句,而这个语句一定要是函数内部的第一行语句,所以说在你创建对象的时候,初始化对象的时候,他要先运行super()这个语句,进入父类调用父类中的this.print();而本身这个创建的这个对象是子类的,因此会调用子类中的print(),在这是很没有执行this.core=core语句,所以没有对this.core赋值,所以这是的this.core是系统默认值0
作者: 江南雨    时间: 2013-5-26 16:39
zjd 发表于 2013-5-26 15:27
不要忘记子类中的构造函数有一个隐藏的super();语句,而这个语句一定要是函数内部的第一行语句,所以说在你 ...

在子类中不是有core=90吗;我是菜鸟,对于编译,运行时不太懂?
作者: First    时间: 2013-5-26 17:50
对象初始化顺序为:

134.* 1.为成员变量开辟空间并赋值为默认值

135.* 2.调用构造函数(为执行方法体)

136.* 3.调用父类构造函数

137.* 4.给成员变量赋初始值

138.* 5.执行代码块

139.* 6.执行构造函数方法体。

140.*

141.* 因此你的函数出现0的情况是因为

142.* 步骤1 执行后 score = 0;

143.* 步骤3 执行时 score = 0;并被打印了;

144.* 步骤4 执行时 socre = 90; 才会执行。

具体情况10楼
作者: zjd    时间: 2013-5-26 18:08
江南雨 发表于 2013-5-26 16:39
在子类中不是有core=90吗;我是菜鸟,对于编译,运行时不太懂?

你这问题提的不错,确实子类中有core=90,如果这个子类是个独立的类的话确实会先运行成员变量,之后再运行构造函数,但是这是个子类,如果是子类是不是要先将父类加载到内存中在运行子类的语句,没有父亲哪来的孩子,说的这些都只适合非静态的,静态的除外,如果将子类中的private int core=90改成private static int core=90那么结果就会使就九十了,实在不理解就记下来,如果是非静态的就按照一般的父类上下执行,要是还不行告诉你个笨法用eclipse调试一下看看到底是怎么运行的,不就o了
作者: 江南雨    时间: 2013-5-26 18:42
zjd 发表于 2013-5-26 18:08
你这问题提的不错,确实子类中有core=90,如果这个子类是个独立的类的话确实会先运行成员变量,之后再运 ...

确实你是对的,理解很深入啊
作者: zjd    时间: 2013-5-26 23:24
江南雨 发表于 2013-5-26 18:42
确实你是对的,理解很深入啊

你要是能给点评分就好了,看我那可怜的技术分呀
作者: 殇_心。    时间: 2013-5-27 10:12
如果问题已解决,请及时修改分类,否则继续提问,谢谢合作!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2