首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >变量多态初始化

变量多态初始化
EN

Stack Overflow用户
提问于 2016-09-26 02:33:33
回答 3查看 1.3K关注 0票数 13

假设您有以下代码

代码语言:javascript
复制
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

现在,如果删除标记为“本行”的行,代码将打印4 4。

  • 我知道如果没有int i=2;line,

A a = new B();将调用A类,将i初始化为4,调用构造函数,

给出了print()方法在class B中的控制权,并最终打印出4条。

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

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

  • 但是,我不明白的是,如果存在int i=2。

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-09-26 03:29:33

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

  1. 方法覆盖
  2. 实例变量阴影
  3. 建造者的先后次序

我将简单地回顾一下您代码中发生的事情,看看您是否理解。

您的代码在概念上看起来如下(跳过main()):

代码语言:javascript
复制
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::i (此时为2)的B::print()上。

因此你所看到的结果

票数 8
EN

Stack Overflow用户

发布于 2016-09-26 02:59:04

新对象中的所有实例变量,包括在超类中声明的变量,都被初始化为它们的默认值- JLS 12.5

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

代码语言:javascript
复制
B() {
    super();
    i = 2;
}

所以当你打电话

代码语言:javascript
复制
A a = new B();

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

票数 7
EN

Stack Overflow用户

发布于 2016-09-26 03:01:02

在你的B类中,"i“的声明隐藏了A中"i”的声明,而在子类中所有对"i“的引用都是指B.i而不是A.i。

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

不能在子类中重写Java实例变量。

你想试试这个以求更多的澄清。

代码语言:javascript
复制
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);
    }
}

输出:

代码语言:javascript
复制
a.i is 4
b.i is 2
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39693922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档