在Constructor中调用方法

时间:2013-04-24 05:12:26

标签: java

下面我有两个班。父母和孩子。 Child类继承自Parent类。在Parent类构造函数中,我调用Parent类的print()方法。

当我在main()方法中为Child类创建Object时,运行Parent类构造函数并调用Child类print()方法而不是Parent类print()方法。

Q1。为什么会发生这种情况。

Q2。为什么i的值为0

public class Sample
{
    public static void main(String[] args) 
    {
        Child objChild = new Child();
        objChild.print();
    }
}

class Parent
{   
    void print()
    {
        System.out.println("i Value");
    }

    Parent()
    {
        print();
    }
}    

class Child extends Parent
{
    int i = 45;

    void print()
    {
        System.out.println("i Value = "+i);
    }
}

OP

i Value = 0
i Value = 45

6 个答案:

答案 0 :(得分:19)

调用子方法的原因是因为虚方法调度是Java中的标准。当您调用该方法时,它会根据对象的实际类型决定在运行时实际调用哪个方法。

至于它打印0的原因,那是因为i尚未设置为45。每个字段都使用该类型的默认值进行初始化,在整数的情况下为0。编写int i = 45时,编译器将在构造函数中生成代码以设置i = 45。但是在调用父构造函数之后它会将此代码放在中。因此,您在使用其预期值初始化变量之前打印变量。

答案 1 :(得分:10)

Java实际上有一些非常明确的规则。本质上,子类中的“int i = 45”代码是子类构造函数的隐式部分,超类构造函数始终首先运行。

事件的顺序是:

  • 创建对象并将所有实例变量清零。
  • 调用超类初始值设定项。
  • 调用超类构造函数。
  • 调用子类初始值设定项(int i = 45;在此示例中)
  • 调用子类构造函数。

当你有一个最终的领域时,这真的很糟糕。您可以在示例中声明“i”final并获得相同的结果!

通常,在构造函数中调用非私有(或至少非最终)方法会遇到麻烦,并且通常是令人讨厌的错误的根源。调用抽象方法是一个非常坏主意(大部分时间)。

答案 2 :(得分:4)

Java初学者:我遇到了你的问题.. 1.当你创建子类的对象时,print()方法只在子类中调用,而不是在父类中,即使父类构造函数调用第一个bcoz,该对象是子类 请参考以下示例。

public class Test
    {
        public static void main(String[] args) 
        {
            //create the object of child class
            Child child = new Child();
        }
    }

    class Parent
    {   
        void print()
        {
            System.out.println("parent>> i ValueOne=");
        }

        Parent()
        {
            System.out.println("parent>> i ValueTwo=");
            print();
        }
    }    

    class Child extends Parent
    {
        int i = 45;


        void print()
        {
            System.out.println("Child>>i Value = "+i);
        }
    }

<强>输出

parent>> i ValueTwo=
Child>>i Value = 0

2.如果此时创建父类对象,则调用父类中的print()方法。 请参考以下示例。

public class Test
    {
        public static void main(String[] args) 
        {
            //create the object of Parent class
            Parent parent = new Parent();
        }
    }

    class Parent
    {   
        void print()
        {
            System.out.println("parent>> i ValueOne=");
        }

        Parent()
        {
            System.out.println("parent>> i ValueTwo=");
            print();
        }
    }    

    class Child extends Parent
    {
        int i = 45;


        void print()
        {
            System.out.println("Child>>i Value = "+i);
        }
    }

<强>输出

parent>> i ValueTwo=
parent>> i ValueOne=

3.我认为你已经清楚了为什么i的值是0或45。

答案 3 :(得分:2)

因为在第一次调用打印方法i时没有初始化为45所以它的打印0。
电话就像这样

  • 子构造函数(因为构造函数从子级链接到父级)
  • 父构造函数
  • print方法(现在这里i未初始化coz子构造函数尚未完成,因此打印默认值i为0)
  • 现在完成父构造函数后,子构造函数i获取其值为45 -
  • 所以现在它在下一次打印方法
  • 上打印45

答案 4 :(得分:2)

首先,我没有在Child类中看到构造函数定义。

如果没有为Child类定义构造函数,则其默认构造函数为:

public Child() {
    super();
}

super();调用Parent类构造函数(超类构造函数)。

但是,您在print()类中定义了Child方法,并且因为它与Parent类中的方法具有相同的签名(名称+参数),所以它会覆盖其超类具有相同签名的方法。

这就是为什么你的Child类调用Parent类构造函数,而它调用自己的print()方法。

- 增加:

第一个i值为0,因为您没有在i类中初始化int变量Parent,并且默认情况下未初始化的int变量的值为0。调用Parent后,它会立即调用Child的{​​{1}}方法,并在print()类中初始化i,所以现在Child是您初始化的值

答案 5 :(得分:1)

您的孩子首先调用您父母的构造函数。此时,我没有使用45值初始化。这就是它打印0(默认的int值)的原因。