繁体   English   中英

在调用超类构造函数方法之前检查子类中的条件

[英]Check conditions in subclass before calling superclass constructor method

我们知道在子类的构造函数体中,父类的构造必须首先声明,否则,我们得到一个编译时错误,这个话题已经讨论过这里

假设调用父构造函数会导致系统资源的大量开销,另一方面,在子类构造函数中,我们需要首先检查一些条件,如果条件满足,我们可以通过父构造函数进行检查,否则就不需要更进一步(假设抛出异常):

class parent {
    parent(Object blah) {
        //Heavy resource consuming tasks
    }
}

class child extends parent {
    child(Object blah, boolean condition) {
        if (!condition) throw new IllegalArgumentException("Condition not satisfied");
        super(blah); //Compile error!
    }
}

如果有人遇到相同的问题,我很好奇是否可以处理这种情况,或者无论浪费多少资源然后抛出异常,我都必须先调用父构造函数。

您可以执行以下操作:

public class Jlaj extends ArrayList<String> {

    public Jlaj(int capacity) {
        super(checkCapacity(capacity));
    }

    private static int checkCapacity(int capacity) {
        if (capacity > 1000)
            throw new IllegalArgumentException();
        return capacity;
    }

    public static void main(String[] args) {
        new Jlaj(1001); // this throws IAE all right
    }
}

请注意,只能以这种方式调用静态方法,这很好:在部分初始化的对象上调用实例方法已经很麻烦,甚至在超类构造函数成为噩梦之前就调用它们。

现在,如果您需要检查不传递给超类的其他一些参数怎么办? 您可以执行以下操作:

public class Jlaj extends ArrayList<String> {

    private final Object foo;

    public Jlaj(int capacity, Object foo) {
        super(checkArgumentsAndReturnCapacity(capacity, foo));
        this.foo = foo;
    }

    private static int checkArgumentsAndReturnCapacity(int capacity, Object foo) {
        if (capacity > 1000)
            throw new IllegalArgumentException();
        if (foo == null)
            throw new NullPointerException();
        return capacity;
    }

    public static void main(String[] args) {
        new Jlaj(1000, null); // throws NPE
    }
}

它可以工作,但是看起来有点难看。 您要将两个无关的东西传递给一个函数,该函数仅返回超类的一个参数。 至少描述性名称对此有所弥补。

如果您绝对需要这样做,则可以使用私有构造函数创建一个静态的builder方法:

class child extends parent {
    private child(Object blah) {
        super(blah);
    }

    static child create(Object blah, boolean condition) {
        if (!condition) throw new IllegalArgumentException("Condition not satisfied");

        return new child(blah);
    }


    public static void main(String[] args) {
        child a = child.create("a", true);
    }
}

我不喜欢使用单独的init方法,因为如果您忘记调用它,则会以无效状态结束。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM