如下代码所示:public class Parent { protected String pStr; public Parent() {
invoke();
} public void invoke() {
System.out.println("Parent invoke " + pStr);
pStr = "Parent pStr";
}
}public class Child extends Parent { private String cStr; public Child() {
super();
} public void invoke() {
System.out.println("Child invoke " + cStr + "; " + pStr);
cStr = "child cStr";
} public static void main(String[] args) {
Child c = new Child();
c.invoke();
}
}
打印出来的结果是:
Child invoke null; null
Child invoke child cStr; null我想问的是:Child c = new Child()这一步 会调用父类构造函数,有一个打印。然后调用子类的构造函数。就是这里吧,子类构造函数是super(),也就是说调用了父类的构造函数对吧,那么为何不再打印一次呢。也就是说最终打印结果我想的是有三行打印。好像哪里理解错了,求指正吧,别的没问题。

解决方案 »

  1.   

    会调用父类的构造函数,但在子类中重写了父类的invoke方法,所以输出的是子类的invoke方法。此时编译器还没加载到成员变量和父类的成员变量所以。都为空 c.invoke();也是调用子类中的方法,这时候子类的成员变量已经加载完成所以就有值,而父类却没有。所以也为空 这都是自己理解的~~ 也不知道是不是完全对  希望能帮到你!
      

  2.   

    我的理解是:
    "Child c = new Child()这一步 会调用父类构造函数,有一个打印。" 这个调用就是通过子类的super()调用的。
    "然后调用子类的构造函数。" 这句应该是理解为,执行子类的构造方法的剩余语句。(楼主的代码里构造方法里没有其他语句了。初始化就算结束了。
    推荐楼主参考一下:
    http://wenwen.soso.com/z/q191435823.htm
      

  3.   

    在创建新的对象时,会先找到super(),同过它来调用父类的构造器,之后轮到子类构造器。在你的代码里写super()是没有意义的,就算不写也会找隐式super的。使用super是为了重复代码的原则,而不是你想的把父类构造器调了又调。
      

  4.   

    public Child() {        
    super();    
    }这个是调用父类的构造方法,楼主应该是知道的,而父类的构造方法 public Parent() {    invoke();    }   调用了invoke();这个方法,然而楼主肯定以为invoke()这个方法就是父类里面的那个,其实是错的,invoke()这个方法应该是子类Child里面的那一个。然而为什么输出又会是NULL呢?这个是因为父类里面
    没有cStr这个变量。总结一下:用super()调用父类构造方法,其实就是调用父类中有的同时又存在于子类的方法和变量。就是取交集啦~~~~~~不知道楼主能不能完全理解,要是不能理解的话再留言吧。
      

  5.   

    public方法调用是多态的,会根据运行时实际创建的对象调用相应的方法。
    所以在构造方法里安全的方案是调用私有方法。
      

  6.   

    改成super(invoke()),你要调父类的方法,总要告诉人家方法名的啊!
      

  7.   

    子类已经有自己的构造方法,肯定就不会去调用父类的,但是你在子类的构造方法中super()了,所以调用了父类构造方法
      

  8.   

    共2次
    一次是子类构造调用父类构造,父类构造调用父类invoke方法
    一次是子类对象对用自己的invoke方法
      

  9.   

    super()写不写都没影响,在有些IDE里这样会被优化掉的,就是自动删除。
    其实是子类的invoke()调用了两遍,第一遍没有初始化都,第二遍时cStr已经初始化了。
    为啥第一遍调用的子类的invoke是因为引用类型是子类Child c = new Child();
    多态当然调用自己运行时类型的方法了。
      

  10.   

    1、super()写不写都没影响,根据继承原理子类都会去调父类构造函数
    2、子类构造函数中调用父类构造函数,父类构造函数中的invoke调的是子类重写的invoke
    3、相当于子类invoke调了两遍,第一遍invoke没有初始化,第二遍有值了
      

  11.   

    因为子类重写了invoke()方法,所以在父类的构造方法中调用的是子类的invoke(),所以会打印第一条
    Child invoke null; null
    构造子类后,再调用invoke()方法时,由于子类的invoke()方法没有
    pStr = "Parent pStr";
    这句,所以打印第二条就为
    Child invoke child cStr; null在一个类实例化时,会首先调用其父类的构造方法,才会调用自己的构造方法。
      

  12.   

    当你显式调用父类构造方法时,子类构造时不会调用父类的默认构造方法的,明白这点你就理解了,写个例子给你看:public class Parent {
    protected String pStr; public Parent() {
    invoke();
    }
    public Parent(String name) {
    System.out.println(name);
    } public void invoke() {
    System.out.println("Parent invoke " + pStr);
    pStr = "Parent pStr";
    }
    }public class Child extends Parent {
    private String cStr; public Child() {
    super("parent");
    } public void invoke() {
    System.out.println("Child invoke " + cStr + "; " + pStr);
    cStr = "child cStr";
    } public static void main(String[] args) {
    Child c = new Child();
    c.invoke();
    }
    }当父类只有有参构造方法时,这个显式调用是必须的。
      

  13.   

    上面例子结果是:
    parent
    Child invoke null; null
      

  14.   

    继承的另一种说法是动态绑定, 学会原理可以更好的帮你理解这个问题。
    动态绑定是相对于静态绑定(又称编译器绑定)而言的,java根据动态绑定决定一个方法的调用是调用哪个类的方法。如:
    Father f = new Son();
    f.someMethod();
    jvm如何解析这段调用someMethod的代码?首先jvm要确定方法调用的主体,即使调用了哪个类的someMethod方法。这点由JTTI支持,java中每个对象的对象头都会存有该对象的类型,对于上面的例子,存的就是com.eros.Son。此时jvm就会关联f对象和Son.someMethod方法。这就是继承的原理。
    何时会执行动态绑定?
    参见http://docs.oracle.com/javase/specs/中invokeSpecial和invokeVirtual指令。
    理解了以上几点几能很快搞清楚你的问题了,
    首先Cliend c = new Child();
    java中构造实例对象前会先递归检查有没有父类,并依次调用父类的构造函数。故会去执行父类构造器,并调用其内的invoke方法,根据上面的分析,invoke方法的调用主体是谁?是this!
    public Parent() {
        this.invoke();
    }
    这段代码跟你的构造器是一样的。
    如果我们在这段代码之前加一句System.out.println(this.getClass());
    你会发现结果是class question.Child。
    ok,接下来就是动态绑定的事了。
    c.invoke同理
    相关refer:
    对象头:http://www.iteye.com/topic/1113318
    this关键字:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.8.3
      

  15.   

    这个编译过不了啊   这里面不是最有一个用public修饰的类吗
      

  16.   

    在类Child中执行 Child c = new Child();
    它会去执行Child类中的构造函数
    public Child() {
            super();
    }
    当它执行到super的时候,就会去执行父类中的Parent的构造函数,然后执行Parent中的invoke()方法.
    执行完后再回来执行Child类中的c.invoke()方法.
    我想你应该想知道为继承的时候会有一次执行交类构造函数,super的时候也会执行一次父类的构造函数,而这里却只执行了一次是吧.
    原因:如果Child类中有重写的构造方法,那么先执行父类的构造方法,再执行Child类的构造方法.
    原因二:因为Child类中有一个super()函数,这个函数只能放在构造函数的第一行,如果放第二行会报错.
    也就是因为这两个原因,才会使得父类方法只执行了一次,当然重点还是因为原因二,你只要记得它的用法就可以了,也算是一个规则性的东西.
      

  17.   

    编译不过的看这里package com.csdn;
     class Parent {
     
        protected String pStr;
     
        public Parent() {
         System.out.println(this.getClass().getName());
            invoke();
        }
     
        public void invoke() {
            System.out.println("Parent invoke " + pStr);
            pStr = "Parent pStr";
        }
    }
     
    public class Child extends Parent {
     
        private String cStr;
     
        public Child() {
            super();
        }
     
        public void invoke() {
            System.out.println("Child invoke " + cStr + "; " + pStr);
            cStr = "child cStr";
        }
     
        public static void main(String[] args) {
            Child c = new Child();
            c.invoke();
        }
    }
      

  18.   

    public Child() {         super();     } 通过super关键字来显示调用父类的构造器,而父类的构造器中调用了invoke() 方法,但是由于子类继承父类,所有子类中的invoke方法覆盖了父类中的invoke方法,所以程序会执行子类中的public void invoke() {         System.out.println("Child invoke " + cStr + "; " + pStr);         cStr = "child cStr";     } ,打印结果为Child invoke null; null而此时变量cStr的值为child cStr,所以在子类对象调用了invoke方法后会打印Child invoke child cStr; null 
    ,pStr为null你应该懂得吧这是我的理解,有不对的地方请指正!
      

  19.   

    首先我要说明一下,两个public类不是写在一起,所以说编译不过的,自己也有点问题。没关注要点。总之感谢各位热情的讨论。谢谢。楼上有几位说得很对,通过讨论大家都更清楚这一过程吧,感谢。
      

  20.   

    17楼的最有道理了。
    invoke();
    <=>
    this.invoke();关键是这个this指谁。