简体   繁体   English

Java字段初始化为抛出异常的函数

[英]Java field initialisation to functions that throw exceptions

I have a problem which reduces down to considering this class: 我有一个问题,减少到考虑这个类:

class myClass
{
    static int s_int = getInteger();

    static int getInteger() throws myClassException
    {
        ...

Here's my problem: this will not compile since getInteger() throws myClassException and I don't have a try catch block when initialising s_int . 这是我的问题:由于getInteger()抛出myClassException并且在初始化s_int时没有try catch块,因此无法编译。

One solution, of course, would be to build a getIntegerAndDealWithTheException() which doesn't throw an exception and call that instead when initialising s_int. 当然,一种解决方案是构建一个getIntegerAndDealWithTheException() ,它不会抛出异常并在初始化s_int时调用它。 But I'd rather not as that is not so pretty: I'd rather not litter the code with stubs. 但我不愿意,因为那不是那么漂亮:我宁愿不用存根来乱丢代码。

Am I missing a syntatic trick here with my initialisation of s_int? 我在初始化s_int时错过了一个合成技巧吗?

Many thanks! 非常感谢!

You could use a static initializer . 您可以使用静态初始化程序 A static initializer is a block of code in between static { and } used to initialize static variables that take more code than a simple declaration and expression. 静态初始化程序是static {}之间的代码块,用于初始化static变量,这些变量比简单的声明和表达式占用更多代码。

class myClass
{
    static int s_int;

    static
    {
       try {
          s_int = getInteger();
       } catch (myClassException e) {
          // Handle it here.
       }
    }

    static getInteger() throws myClassException
    {
        ...

Static initializers may not throw checked Exceptions, according to JLS 11.2.3 . 根据JLS 11.2.3 ,静态初始值设定项可能不会抛出已检查的异常。 To quote: 报价:

It is a compile-time error if a class variable initializer (§8.3.2) or static initializer (§8.7) of a named class or interface can throw a checked exception class. 如果命名类或接口的类变量初始化程序(第8.3.2节)或静态初始化程序(第8.7节)可以抛出已检查的异常类,则会发生编译时错误。

So you must catch the Exception , meaning that you need more than a simple declaration and expression, so a static initializer does the job here. 所以你必须捕获Exception ,这意味着你需要的不仅仅是一个简单的声明和表达式,所以静态初始化器在这里完成工作。

You can initialize static attributes inside the class static block. 您可以在类static块内初始化静态属性。

In your case: 在你的情况下:

class myClass
{
    static int s_int;

    static {
        try {
            s_int = getInteger();
        } catch (myClassException e) {
            // exception handling code
        }
    }

    static getInteger() throws myClassException
    {
        ...

I will elaborate a little on what to do when you catch the exception. 我将详细说明当您发现异常时该怎么做。

The class initialization should be put inside a static initializer. 类初始化应该放在静态初始化器中。 As your compiler warns, you can't leave an uncaught exception inside a static initializer. 在编译器发出警告时,您不能在静态初始化程序中留下未捕获的异常。 You must catch it and do something with it. 你必须抓住它并用它做点什么。 If you can't recover from the exception then your class is not initialized. 如果您无法从异常中恢复,则不会初始化您的类。 Then you must throw an ExceptionInInitializerError that signals that this classes state is invalid. 然后,您必须抛出一个ExceptionInInitializerError ,表示此类状态无效。

class MyClass {
    static int s_int;

static {
    try {
        s_int = getInteger();
    catch (MyClassException e) {
        throw new ExceptionInInitializerError(e);
        // or if it is ok, s_it = some_default_value; 
    }

static int getInteger() throws MyClassException {
   ...

Here you can find a more detailed explanation. 在这里您可以找到更详细的解释。

You could (but probably shouldn't) use a static block: 您可以(但可能不应该)使用static块:

class myClass {

    static int s_int;
    static {
        try {
           s_int = getInteger();
        }
        catch(Exception e) {
            // ...
        }
    }

}

The alternative is to lazy-load the value. 另一种方法是延迟加载值。

class myClass {

    static Integer s_int = null;

    public static int getInteger() throws Exception {
        if(s_int == null) {
            s_int = /* ? */
        }
        return s_int;
    }

    public static void wtv() {
        // never refer to the static member - use the method,
        // which will lazy-load the value
        int s_int = getInteger();
    }

    public static void doSomething() {
        // never refer to the static member - use the method,
        // which will lazy-load the value
        int s_int = getInteger();
    }

}

... and then always refer to getInteger() , never directly to the static member. ...然后总是引用getInteger() ,永远不会直接引用静态成员。

You should consider reading the chapter "Use unchecked expetions" of the book "Clean Code" from Robert C. Martin. 您应该考虑阅读Robert C. Martin所着的“清洁代码”一书中的“使用未经检查的考虑”一章。 After that I do not think you will have this kind of problem. 在那之后,我认为你不会遇到这种问题。

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

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