变量多态性的初始化

时间:2016-09-26 02:33:34

标签: java variables constructor initialization polymorphism

假设您有以下代码

class A {
    int i = 4;

    A() { 
        print();
    }

    void print () {
        System.out.println("A");
    }
}

class B extends A {
    int i = 2;              //"this line"

    public static void main(String[] args){
        A a = new B();
        a.print();
    }

    void print () {
        System.out.println(i);
    }
}

这将打印0 2

现在,如果您删除标有&#34的行;此行" 代码将打印4 4

  • 我明白如果没有int i = 2; line,

A a = new B();将调用A类,将i初始化为4,调用构造函数,
它控制print()中的class B方法,最后打印4.

a.print()将在类B中调用print()方法,因为这些方法将在运行时绑定,这也将使用在类A,4中定义的值。

(当然如果我的推理有任何错误,请告诉我)

  • 然而,我不明白的是,如果有i = 2。

为什么如果插入代码,第一部分(创建对象)将突然打印0而不是4?为什么不将变量初始化为i = 4,而是指定默认值?

3 个答案:

答案 0 :(得分:8)

它是Java中几种行为的组合。

  1. 方法覆盖
  2. 实例变量阴影
  3. 构造函数的顺序
  4. 我将简单介绍代码中发生的事情,看看你是否理解。

    您的代码在概念上看起来像这样(跳过main()):

    class A {
        int i = 0; // default value
    
        A() { 
            A::i = 4;  // originally in initialization statement
            print();
        }
    
        void print () {
            System.out.println("A");
        }
    }
    
    class B extends A {
        int i = 0;              // Remember this shadows A::i
    
        public B() {
            super();
            B::i = 2;
        }
    
        void print () {
            System.out.println(i);
        }
    }
    

    因此,当您在原始main()中调用A a = new B();时,它正在构建B,为此会发生这种情况:

    • A::iB::i都是默认值0
    • super(),表示调用A的构造函数
      • A::i设置为4
      • print()被调用。由于后期绑定,它必然会B::print()
      • B::print()正在尝试打印B::i,其仍为0
    • B::i设置为2

    然后当您在a.print()中拨打main()时,它会被B::print()限制为打印出B::i(此时为2)。

    因此你看到的结果

答案 1 :(得分:7)

  

新对象中的所有实例变量(包括在超类中声明的那些变量)都被初始化为其默认值 - JLS 12.5

因此,您的变量B::i将初始化为0. B中的构造函数将类似于:

B() {
    super();
    i = 2;
}

所以当你打电话

A a = new B();

A中的构造函数将调用B中的print方法,该方法将在类B中打印i,即0。

答案 2 :(得分:5)

在你的情况下,B级," i"隐藏" i"的声明在A中,所有引用" i"在子类中指的是B.i而不是A.i。

所以你在A.i中看到的是java中任何int属性的默认值,它是零。

无法在子类中重写Java实例变量。

您想尝试这一点以获得更多说明。

class B extends A {
    int i = 2;              //"this line"

    public static void main(String[] args){
        B b = new B();
        A a = b;
        System.out.println("a.i is " + a.i);
    System.out.println("b.i is " + b.i);
    }

    void print () {
        System.out.println(i);
    }
}

输出继电器:

a.i is 4
b.i is 2