在私有实用程序类构造函数中使用的首选 Throwable 是什么?

发布于 2024-07-11 03:12:18 字数 643 浏览 14 评论 0原文

Effective Java(第二版),第 4 项讨论使用私有构造函数来强制不可实例化。 这是书中的代码示例:

public final class UtilityClass {
    private UtilityClass() {
        throw new AssertionError();
    }
}

但是,AssertionError 似乎不是正确的抛出方法。 没有任何内容被“断言”,这就是 API 定义 断言错误

在这种情况下是否有不同的 Throwable ? 人们通常会抛出一条带有消息的常规Exception吗? 或者为此编写自定义Exception 是否很常见?

这是相当微不足道的,但最重要的是,我想我只是从风格和标准的角度对它感到好奇。

Effective Java (Second Edition), Item 4, discusses using private constructors to enforce noninstantiability. Here's the code sample from the book:

public final class UtilityClass {
    private UtilityClass() {
        throw new AssertionError();
    }
}

However, AssertionError doesn't seem like the right thing to throw. Nothing is being "asserted", which is how the API defines the use of AssertionError.

Is there a different Throwable that's typically in this situation? Does one usually just throw a general Exception with a message? Or is it common to write a custom Exception for this?

It's pretty trivial, but more than anything I guess I'm just curious about it from a style and standards perspective.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

街道布景 2024-07-18 03:12:18

有一个断言:“我断言这个构造函数永远不会被调用”。 所以,事实上,AssertionError 在这里是正确的。

There is an assertion: "I'm asserting that this constructor will never be called". So, indeed, AssertionError is correct here.

栩栩如生 2024-07-18 03:12:18

我喜欢包括布洛赫的评论:

// Suppress default constructor for noninstantiability

或者更好地将其放入错误中:

private UtilityClass()
{
    throw new AssertionError("Suppress default constructor for noninstantiability");
}

I like including Bloch's comment:

// Suppress default constructor for noninstantiability

Or better yet putting it in the Error:

private UtilityClass()
{
    throw new AssertionError("Suppress default constructor for noninstantiability");
}
吹梦到西洲 2024-07-18 03:12:18

UnsupportedOperationException 听起来是最合适的,尽管检查异常会更好,因为它可能会警告某人在编译时错误地实例化该类。

UnsupportedOperationException sounds like the best fit, though a checked exception would be even better, since it might warn someone erroneously instantiating the class at compile time.

污味仙女 2024-07-18 03:12:18

IllegalAcessError 怎么样? :)

What about IllegalAcessError ? :)

陌若浮生 2024-07-18 03:12:18

当代码需要将 JUnit 作为依赖项包含在内(例如在 Maven 测试范围内)test,则直接转到 Assertion.fail() 方法并受益于清晰度的显着提高。

public final class UtilityClass {
    private UtilityClass() {
        fail("The UtilityClass methods should be accessed statically");
    }
}

当超出测试范围时,您可以使用类似以下内容的内容,这需要静态导入才能像上面一样使用。 import static pkg.Error.fail;

public class Error {
    private static final Logger LOG = LoggerFactory.getLogger(Error.class);
    public static void fail(final String message) {
        LOG.error(message);
        throw new AssertionError(message);
        // or use your preferred exception 
        // e.g InstantiationException
    }
}

其中用法如下。

public class UtilityClassTwo {
    private UtilityClassTwo() {
        Error.fail("The UtilityClass methods should be accessed statically");
    }
}

在其最惯用的形式中,它们都归结为:

public class UtilityClassThree {
    private UtilityClassThree() {
        assert false : "The UtilityClass methods should be accessed statically";
    }
}

内置异常之一,UnsupportedOperationException 可以被抛出到
指示“不支持请求的操作”。

 private Constructor() {
    throw new UnsupportedOperationException(
            "Do not instantiate this class, use statically.");
}

When the code requires the inclusion of the JUnit as a dependency such as within the maven test scope <scope>test</scope>, then go straight to Assertion.fail() method and benefit from significant improvement in clarity.

public final class UtilityClass {
    private UtilityClass() {
        fail("The UtilityClass methods should be accessed statically");
    }
}

When outside the test scope, you could use something like the following, which would require a static import to use like above. import static pkg.Error.fail;

public class Error {
    private static final Logger LOG = LoggerFactory.getLogger(Error.class);
    public static void fail(final String message) {
        LOG.error(message);
        throw new AssertionError(message);
        // or use your preferred exception 
        // e.g InstantiationException
    }
}

Which the following usage.

public class UtilityClassTwo {
    private UtilityClassTwo() {
        Error.fail("The UtilityClass methods should be accessed statically");
    }
}

In its most idiomatic form, they all boil down to this:

public class UtilityClassThree {
    private UtilityClassThree() {
        assert false : "The UtilityClass methods should be accessed statically";
    }
}

One of the built in exceptions, UnsupportedOperationException can be thrown to
indicate that 'the requested operation is not supported'.

 private Constructor() {
    throw new UnsupportedOperationException(
            "Do not instantiate this class, use statically.");
}
最冷一天 2024-07-18 03:12:18

不不不,恕我直言,永远不要抛出AssertionError,除非它来自断言。如果您想要在这里出现 AssertionError,请使用 assert 抛出它(假)。 然后阅读代码的人可以稍后找到它。

更好的是,定义您自己的异常,例如 CantInstantiateUtilityClass。 然后你将得到这样的代码

try {
    // some stuff
} catch (CantInstantiateUtilityClass e) {
    // react
}

,以便捕手的读者知道发生了什么。


让我注意一下,标准仍然AssertionError定义为失败断言的结果,而不是某些初学者认为应该抛出的结果明确定义的信息异常的地方。 遗憾的是,良好的异常纪律可能是 Java 编程中最不值得鼓励的技能。

No no no, with all due respect to Josh Bloch, never throw an AssertionError unless it's from an assertion. If you want an AssertionError here, throw it with assert(false). Then someone reading the code can find it later.

Even better, define your own exception, say CantInstantiateUtilityClass. then you'll have code that says

try {
    // some stuff
} catch (CantInstantiateUtilityClass e) {
    // react
}

so that the reader of the catcher knows what happened.


Let me just note that the standard still defines AssertionError as the result of a failed assertion, not as what some beginner thinks ought to be thrown in place of a well-defined informative exception. Sadly, good exception discipline is perhaps the least encouraged skill in Java programming.

伴我心暖 2024-07-18 03:12:18

断言被破坏意味着您已经破坏了代码的合同规范。 所以这是正确的事情。

但是,正如我假设您将私下实例化一个实例一样,它也会调用构造函数并导致错误 - 除非您有另一个构造函数?

A broken assertion means that you've broken a contract specification of your code. So it's the right thing here.

However, as I assume you'll be privately instantiating an instance, it will also call the constructor and cause an error- unless you have another constructor?

脸赞 2024-07-18 03:12:18

您可以创建自己的类来扩展 Throwable,例如:

class NoninstantiabilityError extends Throwable

这具有以下优点:

  • 名称表明了问题
  • 因为它直接扩展了 Throwable,所以不太可能被捕获由于
  • 它直接扩展了 Throwable,因此会对其进行检查,并且意外调用相应的构造函数将需要捕获异常用法

示例:

public final class UtilityClass {
    private UtilityClass() throws NoninstantiabilityError {
        throw new NoninstantiabilityError();
    }

    ...
}

You can create your own class extending Throwable, e.g.:

class NoninstantiabilityError extends Throwable

This has the following advantages:

  • The name indicates the problem
  • Because it directly extends Throwable it is unlikely that it will be caught by accident
  • Because it directly extends Throwable it is checked and calling the respective constructor by accident would require catching the exception

Usage example:

public final class UtilityClass {
    private UtilityClass() throws NoninstantiabilityError {
        throw new NoninstantiabilityError();
    }

    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文