将'this'转换为超类构造函数中的子类

时间:2013-01-08 10:51:26

标签: java android constructor downcast

有两个类:ABBA的子类。 A存储B的引用,在某些情况下可能 this的引用。

public B b;

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

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

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

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

2 个答案:

答案 0 :(得分:1)

- 如果其他类也延伸到A ,则会出现问题,然后默认情况下可以将其强制转换为B类。 /强>

- 我建议您使用instanceof对此事进行排序....

答案 1 :(得分:1)

除了良好的OO设计之外,这个星座不会破坏任何其他规则。 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自己的构造函数覆盖,这非常违反直觉。

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