Java:构造函数中的异常:有问题吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7532078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:22:03  来源:igfitidea点击:

Java: Exception in constructors: Problematic or not?

javaexceptionconstructor

提问by zw324

I am recently thinking about if throwing constructor from Java is good or not. Currently this is what I gathered:

我最近在考虑从 Java 抛出构造函数是否好。目前这是我收集的:

  1. Can constructors throw exceptions in Java?

    Here, Mr. StackOverflow (aka Jon Skeet) does not seem to hold anything against it, but he did hint about having subclass throwing exceptions. What will happen (anything bad?) when subclass throws exceptions?

  2. http://futuretask.blogspot.com/2006/05/java-tip-10-constructor-exceptions-are.html

    This blog post "Constructor Exceptions are Evil" tells me a way to show that constructor exceptions could be dangerous. However, the example seem to be really esoteric. Is there any real danger here?

  3. I am thinking that if static factory methods (Effective Java 2nd ed., Item 1) are used instead of public constructors, we could safely remove the exceptions from constructors to the static factory method. Is this a valid way to avoid constructor exceptions and is this useful or used in anywhere?

  1. 构造函数可以在 Java 中抛出异常吗?

    在这里,StackOverflow 先生(又名 Jon Skeet)似乎并不反对它,但他确实暗示了子类会抛出异常。当子类抛出异常时会发生什么(有什么不好的?)?

  2. http://futuretask.blogspot.com/2006/05/java-tip-10-constructor-exceptions-are.html

    这篇博客文章“构造函数异常是邪恶的”告诉我一种方法来证明构造函数异常可能是危险的。然而,这个例子似乎非常深奥。这里真的有危险吗?

  3. 我在想,如果使用静态工厂方法(Effective Java 2nd ed., Item 1)而不是公共构造函数,我们可以安全地将异常从构造函数移除到静态工厂方法。这是避免构造函数异常的有效方法吗,这是否有用或在任何地方使用?

Any inputs are helpful & appreciated. Thanks!

任何输入都是有帮助和赞赏的。谢谢!

采纳答案by jtahlborn

There is nothing wrong with exceptions in constructors (or factory methods, either way is fine). sometimes, doing too much work in a constructor can be a poor design, and may make sense to move to a factory method.

构造函数(或工厂方法,无论哪种方式都可以)中的异常并没有错。有时,在构造函数中做太多工作可能是一个糟糕的设计,并且转移到工厂方法可能是有意义的。

the only thing that point 2 proves is that exceptions in constructors are not an adequate security mechanism for protecting a class from evil usage. however, there are any number of ways to subvert such a design, which is why the only way to trulyrun secure code in java is running with a SecurityManager. so point 2 is just a straw man argument.

第 2 点唯一证明的是,构造函数中的异常不是保护类免受恶意使用的足够安全机制。然而,有许多方法可以颠覆这种设计,这就是为什么在 java 中真正运行安全代码的唯一方法是使用 SecurityManager 运行。所以第2点只是一个稻草人的论点。

回答by Jon Skeet

My point about a subclass throwing an exception is a situation like this:

我关于子类抛出异常的观点是这样的:

public class Parent {
    private final InputStream stream;

    public Parent() {
        stream = new FileInputStream(...);
    }

    public void close() throws IOException {
        stream.close();
    }
}

public class Child extends Parent {
    public Child() {
        // Implicit call to super()
        if (someCondition) {
            throw new RuntimeException();
        }
    }
}

Now the Childclass really shouldcall close()if it's going to throw an exception. Of course, if close()is overridden by yet another layer of inheritance, that could alsocause problems. Just another example of how inheritance gets messy.

现在,如果要抛出异常,Child该类真的应该调用close()。当然,如果close()是通过继承的又一层覆盖,这可能导致问题。这是继承如何变得混乱的另一个例子。

I still think it's basically fine for constructors to throw exceptions. Even your second link was more about an evil way of capturing the not-successfully-constructed object rather than really about constructor exceptions being evil - it certainly doesn't give any reasonsfor not throwing exceptions from constructors. It doesn't even give the messy situation I mentioned.

我仍然认为构造函数抛出异常基本上没问题。甚至你的第二个链接更多地是关于捕获未成功构造的对象的邪恶方式,而不是真正关于构造函数异常是邪恶的 - 它当然没有给出任何不从构造函数抛出异常的理由。它甚至没有给出我提到的混乱情况。

Factory methods couldpotentially help, but as far as the caller is concerned the result is the same: they don't get to see the partially-constructed object. Unless you really needto do something like clean-up on an object which was constructed but then failed some element of validation, I don't think that should be a reason to use factory methods instead of constructors. (There are otherreasons to do so, but that's a different matter.)

工厂方法可能会有所帮助,但就调用者而言,结果是相同的:他们看不到部分构造的对象。除非您真的需要对已构造但随后未通过某些验证元素的对象进行清理,否则我认为这不应成为使用工厂方法而不是构造函数的理由。(这样做还有其他原因,但那是另一回事。)

回答by Scorpion

I believe throwing exceptions from constructors is fine, more so the one's which checks for the preconditions to a successful object creation, example IllegalArgumentException. However, I do not believe that constructors are the right place to handle business logic or throw business exception/ custom exceptions.

我相信从构造函数抛出异常很好,更重要的是检查成功创建对象的先决条件,例如 IllegalArgumentException。但是,我不认为构造函数是处理业务逻辑或抛出业务异常/自定义异常的正确位置。

As for the reasons cited to not throw an exception, IMHO they are quite contrived; bottom line is if a careless developer wishes to do something evil he can find numerous ways to do it and there's no stopping till the developer does a self review of the code/ follows best practices.

至于所引用的不抛出异常的原因,恕我直言,他们非常做作;最重要的是,如果一个粗心的开发人员希望做一些邪恶的事情,他可以找到很多方法来做,并且在开发人员对代码进行自我/遵循最佳实践之前不会停止。