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

Java 在调用超类构造函数方法之前,请检查子类中的条件,java,inheritance,constructor,Java,Inheritance,Constructor,正如我们在子类的构造函数体中所知道的那样,父构造函数必须是第一条语句,否则会出现编译时错误,本主题已经讨论过了 让我们假设调用父构造函数会导致系统资源的巨大成本,另一方面在子类构造函数中,我们需要首先检查一些条件,如果条件满足,我们可以通过父构造函数,否则就不需要进一步检查(假设抛出一个异常): 如果有人有同样的问题,我很好奇是否有办法处理这种情况,或者我必须先调用父构造函数,不管它浪费了多少资源,然后抛出异常?您可以这样做: public class Jlaj extends ArrayLis

正如我们在子类的构造函数体中所知道的那样,父构造函数必须是第一条语句,否则会出现编译时错误,本主题已经讨论过了

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


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

您可以这样做:

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类Jlaj扩展了ArrayList{
公共Jlaj(内部容量){
超级(检查容量(容量));
}
专用静态整数检查容量(整数容量){
如果(容量>1000)
抛出新的IllegalArgumentException();
返回能力;
}
公共静态void main(字符串[]args){
新Jlaj(1001);//这没问题
}
}
注意,您只能以这种方式调用静态方法,这很好:在部分初始化的对象上调用实例方法已经是一个巨大的麻烦,甚至在超类构造函数之前调用它们将是一场噩梦

现在,如果您需要检查一些未传递给超类的其他参数,该怎么办?您可以这样做:

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
    }
}
public类Jlaj扩展了ArrayList{
私有最终对象foo;
公共Jlaj(内部容量,对象foo){
超级(检查参数和返回容量(容量,foo));
this.foo=foo;
}
私有静态int-checkArguments和returnCapacity(int-capacity,对象foo){
如果(容量>1000)
抛出新的IllegalArgumentException();
if(foo==null)
抛出新的NullPointerException();
返回能力;
}
公共静态void main(字符串[]args){
新的Jlaj(1000,null);//抛出NPE
}
}

它可以工作,但看起来有点难看。您正在将两个不相关的内容传递到一个只返回超类参数的函数中。至少描述性名称在某种程度上弥补了这一点。

您可以执行以下操作:

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类Jlaj扩展了ArrayList{
公共Jlaj(内部容量){
超级(检查容量(容量));
}
专用静态整数检查容量(整数容量){
如果(容量>1000)
抛出新的IllegalArgumentException();
返回能力;
}
公共静态void main(字符串[]args){
新Jlaj(1001);//这没问题
}
}
注意,您只能以这种方式调用静态方法,这很好:在部分初始化的对象上调用实例方法已经是一个巨大的麻烦,甚至在超类构造函数之前调用它们将是一场噩梦

现在,如果您需要检查一些未传递给超类的其他参数,该怎么办?您可以这样做:

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
    }
}
public类Jlaj扩展了ArrayList{
私有最终对象foo;
公共Jlaj(内部容量,对象foo){
超级(检查参数和返回容量(容量,foo));
this.foo=foo;
}
私有静态int-checkArguments和returnCapacity(int-capacity,对象foo){
如果(容量>1000)
抛出新的IllegalArgumentException();
if(foo==null)
抛出新的NullPointerException();
返回能力;
}
公共静态void main(字符串[]args){
新的Jlaj(1000,null);//抛出NPE
}
}

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

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

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方法,因为如果忘记调用它,将导致状态无效。

如果确实需要这样做,可以使用私有构造函数创建静态生成器方法:

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方法,因为如果忘记调用它,将导致无效状态。

的可能副本不要在构造函数中放入这样的资源密集型逻辑。创建一个轻量级构造函数和一个单独的
init()
方法来完成繁重的工作。@azurefrog当我使用init()时也是如此我仍然必须首先调用父构造函数place@CollinD,这不完全是重复的。它没有问为什么。它只是问了一个绕过这一点的方法,也有一个合理的理由。@CollinD我已经提到了你在读我的文章时评论的链接!我是问我如何处理这种情况,而不是试图绕过它。可能吧不要将这种资源密集型逻辑放在构造函数中。创建一个轻量级构造函数和一个单独的
init()
方法来完成繁重的工作。@azurefrog在使用init()时也是如此我仍然必须首先调用父构造函数place@CollinD,这不完全是重复的。它没有问为什么。它只是问了一个绕过这一点的方法,还有一个合理的原因。@CollinD我已经提到了你在读我的文章时评论的链接!我是问我如何处理这种情况,而不是试图绕过它。谢谢,这正是我想要的,如果子类构造函数和超类构造函数的参数数量不匹配怎么办?您的解决方案在这种情况下也能工作吗?还是我应该使用Cyril answer之类的生成器方法?@FarShaD,从技术上讲,它可以工作,但看起来很难看。稍后将添加一个示例。谢谢,这正是我想要的正在查找子类和超类构造的参数数量