Java 初始化子类字段

Java 初始化子类字段,java,initialization,field,subclass,extending,Java,Initialization,Field,Subclass,Extending,考虑一个简单的AClass: class AClass { private AContent content; AClass(AContent content) { this.content = content; print(); } protected void print() { System.out.println("AClass content is "+ content.getValue());

考虑一个简单的
AClass

class AClass {

    private AContent content;

    AClass(AContent content) {

        this.content = content;
        print();
    }

    protected void print() {

        System.out.println("AClass content is "+ content.getValue());
    }
}
其中,
a内容的定义如下:

class AContent {

    int getValue() {
        return 1;
    }
}
class BContent extends AContent{

    @Override
    int getValue() {
        return 2;
    }
}
b类
,扩展了
a类
,并由
b内容
初始化,该内容扩展了
a内容
,如下所示:

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());
    }
}
其中,
b内容
由以下内容定义:

class AContent {

    int getValue() {
        return 1;
    }
}
class BContent extends AContent{

    @Override
    int getValue() {
        return 2;
    }
}
构造
b类
对象:

public static void main(String[] args) {

        new BClass(new BContent());
}
正如预期的那样,由于尝试打印而产生的
NullPointerException

System.out.println("BClass content is "+ content.getValue());
在初始化内容之前
为了克服它,我考虑了两种选择:
a、 从构造函数中删除
print()
调用。这将起作用,但对于我所需要的功能来说并不可取。
b、 将
内容设置为静态,并使用静态方法对其进行初始化:

private static BContent content;

BClass(BContent content) {

  super(init(content));
}

private static BContent init(BContent content) {

    BClass.content = content;
    return content;
}
这会起作用,但看起来很丑陋

我正在寻求有关如何更好地构造此类代码的建议,以使其不仅具有功能,而且符合常见做法。一种方法是将
b内容
传递给
AClass
构造函数。这将起作用,因为
BContent
AContent
的子类:

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
时,您的
print
方法将已初始化,您就没事了

如果您确实需要在b类中知道
b内容
的类型,请使用泛型:

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());
    }
}
类AClass{
//使其受保护,以便子类可以访问
//(通过受保护的get方法可能更好)
受保护的内容;
...
}
类BClass扩展了AClass{
B类(B内容){
超级(内容);
}
@凌驾
受保护的无效打印(){
//现在,如果我愿意,我可以用B内容做一些不需要的事情
//由于已知B内容的类型,因此可能使用A内容
System.out.println(“b类内容为”+content.getValue());
}
}

基于@Oliver Dain的回答,我最终得出:

 class AClass <T extends AContent>{

        private T content;

        AClass(T content) {

            this.content = content;
            print();
        }

        protected void print() {

            System.out.println("Content is "+ getContent().getValue());
        }

        public T getContent() {
            return content;
        }
    }

class BClass extends AClass<AContent> {

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

    public static void main(String[] args) {

        new BClass(new BContent());
    }
}

class AContent {

    int getValue() {
        return 1;
    }
}

class BContent extends AContent{

    @Override
    int getValue() {
        return 2;
    }
}
类AClass{
私有内容;
AClass(T内容){
this.content=内容;
打印();
}
受保护的无效打印(){
System.out.println(“内容是”+getContent().getValue());
}
公共T getContent(){
返回内容;
}
}
类BClass扩展了AClass{
B类(B内容){
超级(内容);
}
公共静态void main(字符串[]args){
新的b类(新的b内容());
}
}
类内容{
int getValue(){
返回1;
}
}
类BContent扩展了AContent{
@凌驾
int getValue(){
返回2;
}
}

b类
b内容
传递给
AClass
构造函数,或者我遗漏了什么?您将其传递给AClass,但随后通过将其复制到具有相同名称的B类中的属性来复制和隐藏它。在上面的答案中,只有AClass引用了
内容
B类
引用
内容
引用
系统.out.println(“B类内容是”+content.getValue())导致
NullPointerException
,因为它尚未初始化。是的。但由于AClass是其父级,因此它可以从父级访问它。而且,由于父级在子级之前初始化,因此您将是安全的。你在这里试过这个建议,发现它不管用吗?