2

有两个类:ABB是 的子类AA存储 的引用,在某些情况下B也可能是对的引用。this

public B b;

在 的构造函数中,将引用转换为(前提是我知道正在构造的对象的具体类型是)A是否合法?(语法上,我知道;设计方面,它可能反映了糟糕的组件设计;但我想知道它是否有任何严重的风险,因此是不可接受的。)thisBB

public A(...parameters) {
    b = (B) this;
}

问题出现了,因为此时, 的构造函数B尚未完成(因为 this 恰好在B调用时运行super)。

我知道b在其构造函数完成之前访问意味着我正在访问(语义上)未初始化的成员(所以我从不这样做),但这就是全部吗?

4

2 回答 2

1

-如果有任何其他类也扩展到 A,那么问题就会出现,那么它可能会默认转换为 B 类。

-我建议你用instanceof它来解决这个问题......

于 2013-01-08T10:56:33.663 回答
1

除了良好的面向对象设计之外,这个星座不违反任何其他规则。Java 已为这种情况做好了准备,因为 B 的所有字段甚至在调用任何构造函数之前都已初始化,如以下示例所示:

public class A {

    int aMember;

    public static final void main(String[] args) {
        new B();
    }

    A() {
        B b = (B) this;

        System.out.println("in A(), before b.bMember    has been set here, b.bMember    = " + b.bMember);
        System.out.println("in A(), before this.aMember has been set here, this.aMember = " + this.aMember);

        this.aMember = 5;
        b.bMember = 1; // will be overwritten in B()

        System.out.println("in A(), after  b.bMember    has been set here, b.bMember    = " + b.bMember);
        System.out.println("in A(), after  this.aMember has been set here, this.aMember = " + this.aMember);
    }
}

--

public class B extends A {

    int bMember;

    B() {
        super(); // invokes A()

        System.out.println("in B(), before this.bMember has been set here, this.bMember = " + this.bMember);

        this.bMember = 6;

        System.out.println("in B(), after  this.bMember has been set here, this.bMember = " + this.bMember);
    }
}

这输出:

in A(), before b.bMember    has been set here, b.bMember    = 0
in A(), before this.aMember has been set here, this.aMember = 0
in A(), after  b.bMember    has been set here, b.bMember    = 1
in A(), after  this.aMember has been set here, this.aMember = 5
in B(), before this.bMember has been set here, this.bMember = 1
in B(), after  this.bMember has been set here, this.bMember = 6

这意味着在 A() 中,B 的成员变量在设置之前与 A 的成员变量处于相同的状态。两者都已初始化为其默认值(0 表示 int,false 表示布尔值,null 表示对象,...)并且可以使用。一个很大的坑是B的成员变量可以在A()中设置,但是可以被B自己的构造函数覆盖,这很违反直觉。

我喜欢这个问题,因为它表达得简单明了,但它提出了更复杂的问题,这些问题涉及到其他主题,如编译器内部和对象创建的细节。

于 2013-01-08T11:50:07.593 回答