黑马程序员技术交流社区

标题: 翻到以前一个子父类构造对象时的问题 [打印本页]

作者: 轻语。    时间: 2014-4-26 10:45
标题: 翻到以前一个子父类构造对象时的问题
本帖最后由 伍叶竹 于 2014-4-26 13:20 编辑
  1. class Parent {
  2.     private int flag=0;
  3.     public Parent(){
  4.         System.out.println("Parent is creating..");
  5.         eat();
  6.     }
  7.     public void eat(){
  8.         System.out.println("Parent is eat: "+flag);
  9.     }

  10. }

  11. public class Son extends Parent {
  12.     {System.out.println("i am ok.");}
  13.         
  14.     private int flag=1;
  15.     public Son(){
  16.         System.out.println("Son is creating..");
  17.         eat();
  18.     }
  19.     public void eat(){
  20.         System.out.println("Son is eat: "+flag);
  21.     }
  22.    
  23.     public static void main(String[] args){
  24.         Parent p=new Son();
  25.     }

  26. }
复制代码
打印的结果是:Parent is creating
Son is eat: 0
i am ok.
Son is creating..
Son is eat: 1
大概问题是:第二行打印结果为什么flag的值是0?




作者: skill20    时间: 2014-4-26 10:56
多态在子父类中的成员上的体现的特点:
1,成员变量:在多态中,子父类成员变量同名。
        在编译时期:参考的是引用型变量所属的类中是否有调用的成员。(编译时不产生对象,只检查语法错误)
        运行时期:也是参考引用型变量所属的类中是否有调用的成员。
        简单一句话:无论编译和运行,成员变量参考的都是引用变量所属的类中的成员变量。
        再说的更容易记忆一些:成员变量 --- 编译运行都看 = 左边。
2,成员函数。
        编译时期:参考引用型变量所属的类中是否有调用的方法。
        运行事情:参考的是对象所属的类中是否有调用的方法。
        为什么是这样的呢?因为在子父类中,对于一模一样的成员函数,有一个特性:覆盖。
        简单一句:成员函数,编译看引用型变量所属的类,运行看对象所属的类。
        更简单:成员函数 --- 编译看 = 左边,运行看 = 右边。
3,静态函数。
        编译时期:参考的是引用型变量所属的类中是否有调用的成员。
        运行时期:也是参考引用型变量所属的类中是否有调用的成员。
        为什么是这样的呢?因为静态方法,其实不所属于对象,而是所属于该方法所在的类。
        调用静态的方法引用是哪个类的引用调用的就是哪个类中的静态方法。
        简单说:静态函数 --- 编译运行都看 = 左边。
作者: 轻语。    时间: 2014-4-26 11:03
skill20 发表于 2014-4-26 10:56
多态在子父类中的成员上的体现的特点:
1,成员变量:在多态中,子父类成员变量同名。
        在编译时期:参考的 ...

从第一点来看,也就是说这里引用变量是父类,所属是父类,所以参考的是父类中的成员变量?所以打印的是父类中的flag的值0吗?
作者: skill20    时间: 2014-4-26 11:05
伍叶竹 发表于 2014-4-26 11:03
从第一点来看,也就是说这里引用变量是父类,所属是父类,所以参考的是父类中的成员变量?所以打印的是父 ...

恩,我是这样理解的。
作者: 轻语。    时间: 2014-4-26 11:08
skill20 发表于 2014-4-26 11:05
恩,我是这样理解的。

改了一下父类中flag的值。 运行打印结果还是0.
作者: peku    时间: 2014-4-26 11:53
本帖最后由 peku 于 2014-4-26 11:59 编辑

问题在于类中变量的初始化在什么时候进行---请看红色部分
class Parent {
    private int flag=0;
    public Parent(){
        System.out.println("Parent is creating..");
        eat();//三.由于被子类覆盖,所以执行子类中的eat
    }
    public void eat(){
        System.out.println("Parent is eat: "+flag);
    }

}

public class Son extends Parent {
    {System.out.println("i am ok.");}
        
    private int flag=1;//一.这句话会先在内存中定义变量,但不会初始化,使用默认的0值
    public Son(){//二.执行super(),然后执行int flag=1进行初始化,
        System.out.println("Son is creating..");
        eat();
    }
    public void eat(){
        System.out.println("Son is eat: "+flag);//四.此时打印的是默认的flag值,即为0,因为还未进行初始化语句。
    }
   
    public static void main(String[] args){
        Parent p=new Son();
    }

}所以进行的顺序是定义变量flag,此时flag是默认值0;执行super函数;进行子类中的eat函数,此时打印flag默认值0;回到构造son函数中初始化flag=1;进行其他语句。

作者: skill20    时间: 2014-4-26 11:59
伍叶竹 发表于 2014-4-26 11:08
改了一下父类中flag的值。 运行打印结果还是0.

那我理解错了。
作者: 轻语。    时间: 2014-4-26 12:22
peku 发表于 2014-4-26 11:53
问题在于类中变量的初始化在什么时候进行---请看红色部分
class Parent {
    private int flag=0;

嗯嗯  初始化为0 未赋值。 3Q
作者: 轻语。    时间: 2014-4-26 12:25
skill20 发表于 2014-4-26 11:59
那我理解错了。

没有呢,你的笔记很有帮助。 我这里只是因为有个初始化为0  但其实还没有到赋值。 所以第一次打印的时候是0
作者: 你为谁归来    时间: 2014-4-26 13:15
当你new-son的对象时候调用构造方法,但是子类的构造方法隐藏着一个super()调用父类的构造方法,实际上是父类的构造方法先运行,这个时候flag还没有被赋值。默认的值是0,所以打印0.




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