动态加载可能异常的对象是否可以声明为final?

时间:2012-11-27 22:22:16

标签: java variables dynamic exception-handling final

起初我只是提出Image课程的问题,但我想尽可能广泛地适用。

基本上,就是这个场景。我正在为GUI常量制作一个文件,在这个文件中,我想为每个Image我使用的最终变量。所以我的字段被声明为UP_ARROW

public static final Image UP_ARROW;

然后我尝试在ImageIO API时加载它们,如下所示:

static {
    UP_ARROW = ImageIO.read(new File("img/upArrow.png"));
}

不幸的是,这不是有效的,可编译的代码,因为它明确地throws IOException,我必须处理它。所以我修改它并用try / catch包围它:

static {
    try {
        UP_ARROW = ImageIO.read(new File("img/upArrow.png"));
    }
    catch(IOException ioe) {
        //TODO
    }
}

现在我遇到了不同的编译器错误。这一次它表示该领域可能尚未初始化。好的,这是有道理的。谢谢你指出我的编译器。这似乎很容易解决:

static {
    try {
        UP_ARROW = ImageIO.read(new File("img/upArrow.png"));
    }
    catch(IOException ioe) {
        UP_ARROW = null;
    }
}

现在,无论如何,UP_ARROW必须使用我的图片或null填充。我准备宣布胜利并继续前进。但现在我得到另一个,意外的编译器错误:

The final field UP_ARROW may already have been assigned

...再次挫败,编译!

因此问题:有没有办法解决这个问题,这样我可以在运行时动态加载最终字段?或者我宣布失败并简单地使Image成为非决赛?

此外,关于编译器为什么不允许这样做的解释也会有所帮助。据我了解,基于上面的代码,UP_ARROW对象在到达catch{}之前无法分配,因为那是什么必须抛出异常。因此,如果try{}成功执行,则只进行一次分配。如果未成功执行,则仍然只进行一次分配。这怎么没有效?

2 个答案:

答案 0 :(得分:4)

以下应该这样做:

static {
    Image up_arrow = null;
    try {
        up_arrow = ImageIO.read(new File("img/upArrow.png"));
    }
    catch(IOException ioe) {
        // log the error?
    }
    UP_ARROW = up_arrow;
}

将最终作业包含在finally块中可能是有意义的。

答案 1 :(得分:1)

NPE的答案很好,但我认为这个更好(基于他和他)更好:

public enum Arrows {
    UP ("img/upArrow.png"),
    DOWN ("img/downArrow.png"),
    LEFT ("img/leftArrow.png"),
    RIGHT ("img/rightArrow.png");

    public final Image myImage;

    private Arrows(String fileName) {
        Image tempImage;
        try {
            tempImage = ImageIO.read(new File(fileName));
        } catch (IOException e) {
            tempImage = null;
        }
        myImage = tempImage;
    }
}

这可以解决您的问题,并为您提供enum超过static final个变量的所有优势。