考虑一个简单的AClass

class AClass {

    private AContent content;

    AClass(AContent content) {

        this.content = content;
        print();
    }

    protected void print() {

        System.out.println("AClass content is "+ content.getValue());
    }
}


其中AContent由以下定义:

class AContent {

    int getValue() {
        return 1;
    }
}


BClass,扩展AClass,并由BContent初始化,该扩展扩展AContent,如下所示:

class BClass extends AClass {

    private BContent content;

    BClass(BContent content) {
        super(content);
        this.content = content;
    }

    @Override
    protected void print() {

        System.out.println("BClass content is "+ content.getValue());
    }
}


其中BContent由以下定义:

class BContent extends AContent{

    @Override
    int getValue() {
        return 2;
    }
}


构造一个BClass对象:

public static void main(String[] args) {

        new BClass(new BContent());
}


产量,可以预期是尝试打印导致的NullPointerException

System.out.println("BClass content is "+ content.getValue());


在内容初始化之前。
为了克服它,我考虑了两种选择:
从构造函数中删除print()调用。这将起作用,但对于我需要的功能不是理想的。
b。使content为静态并使用静态方法对其进行初始化:

private static BContent content;

BClass(BContent content) {

  super(init(content));
}

private static BContent init(BContent content) {

    BClass.content = content;
    return content;
}


这可以工作,但是看起来很丑陋。
我正在寻求有关如何更好地构造此类代码的建议,以使其不仅功能正常,而且符合常规做法。

最佳答案

一种方法是将BContent传递给AClass构造函数。这将起作用,因为BContentAContent的子类:

class AClass {
    // Make protected so subclasses can access
    // (probably better via a protected get method)
    protected AContent content;
    ...
}

class BClass extends AClass {

    BClass(BContent content) {
        super(content);
    }

    @Override
    protected void print() {
        System.out.println("BClass content is "+ content.getValue());
    }
}


print方法被调用为content的时间将被初始化,您将可以。

如果您实际上需要在BClass中知道BContent的类型,请使用泛型:

class AClass<ContentT extends AContent> {
    // Make protected so subclasses can access
    // (probably better via a protected get method)
    protected ContentT content;
    ...
}

class BClass extends AClass<BContent> {

    BClass(BContent content) {
        super(content);
    }

    @Override
    protected void print() {
        // Now if I wanted I could do things with BContent that aren't
        // possible with AContent since the type of BContent is known
        System.out.println("BClass content is "+ content.getValue());
    }
}

10-04 19:46