【问题标题】:Check conditions in subclass before calling superclass constructor method在调用超类构造方法之前检查子类中的条件
【发布时间】:2016-07-14 18:00:41
【问题描述】:

正如我们在子类的构造函数体中所知道的,父构造函数必须是第一个语句,否则我们会得到编译时错误,这个话题已经讨论过here

假设调用父类构造函数会消耗大量系统资源,而子类构造函数需要先检查一些条件,如果条件满足很满意,我们可以通过父构造函数,否则不需要更进一步(假设抛出异常):

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!
    }
}

如果有人遇到同样的问题,我很好奇是否有办法处理这种情况,或者我必须先调用父构造函数,不管它浪费了多少资源,然后抛出异常?

【问题讨论】:

  • 不要将这种资源密集型逻辑放在构造函数中。制作一个轻量级构造函数和一个单独的 init() 方法来完成繁重的工作。
  • @azurefrog 所以当我使用 init() 时,我仍然必须首先调用父构造函数
  • @CollinD,这不完全是重复的。它不问为什么。它只是要求一种解决此问题的方法,并且也是出于理智的原因。
  • @CollinD 如果您阅读我的帖子,我已经提到了您评论的链接!我在询问我可以处理这种情况的方法,而不是试图绕过它。

标签: java inheritance constructor


【解决方案1】:

你可以这样做:

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
    }
}

它有效,但看起来有点难看。您将两个不相关的东西传递给一个只返回超类参数的函数。至少描述性名称在某种程度上弥补了这一点。

【讨论】:

  • 谢谢,这正是我想要的
  • 如果子类和超类构造函数的参数数量不匹配怎么办?您的解决方案是否也适用于这种情况,或者我应该使用像 Cyril answer 这样的构建器方法?
  • @FarShaD,好吧,从技术上讲它可以工作,但看起来很难看。稍后将添加一个示例。
【解决方案2】:

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

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 方法,因为如果您忘记调用它,最终会出现无效状态。

【讨论】:

  • 感谢回复,静态方法适合我的情况
  • 这种解决方案的优点是,无论子类构造函数有多少参数,它总是有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
相关资源
最近更新 更多