簡體   English   中英

Java字段初始化為拋出異常的函數

[英]Java field initialisation to functions that throw exceptions

我有一個問題,減少到考慮這個類:

class myClass
{
    static int s_int = getInteger();

    static int getInteger() throws myClassException
    {
        ...

這是我的問題:由於getInteger()拋出myClassException並且在初始化s_int時沒有try catch塊,因此無法編譯。

當然,一種解決方案是構建一個getIntegerAndDealWithTheException() ,它不會拋出異常並在初始化s_int時調用它。 但我不願意,因為那不是那么漂亮:我寧願不用存根來亂丟代碼。

我在初始化s_int時錯過了一個合成技巧嗎?

非常感謝!

您可以使用靜態初始化程序 靜態初始化程序是static {}之間的代碼塊,用於初始化static變量,這些變量比簡單的聲明和表達式占用更多代碼。

class myClass
{
    static int s_int;

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

    static getInteger() throws myClassException
    {
        ...

根據JLS 11.2.3 ,靜態初始值設定項可能不會拋出已檢查的異常。 報價:

如果命名類或接口的類變量初始化程序(第8.3.2節)或靜態初始化程序(第8.7節)可以拋出已檢查的異常類,則會發生編譯時錯誤。

所以你必須捕獲Exception ,這意味着你需要的不僅僅是一個簡單的聲明和表達式,所以靜態初始化器在這里完成工作。

您可以在類static塊內初始化靜態屬性。

在你的情況下:

class myClass
{
    static int s_int;

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

    static getInteger() throws myClassException
    {
        ...

我將詳細說明當您發現異常時該怎么做。

類初始化應該放在靜態初始化器中。 在編譯器發出警告時,您不能在靜態初始化程序中留下未捕獲的異常。 你必須抓住它並用它做點什么。 如果您無法從異常中恢復,則不會初始化您的類。 然后,您必須拋出一個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 {
   ...

在這里您可以找到更詳細的解釋。

您可以(但可能不應該)使用static塊:

class myClass {

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

}

另一種方法是延遲加載值。

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();
    }

}

...然后總是引用getInteger() ,永遠不會直接引用靜態成員。

您應該考慮閱讀Robert C. Martin所着的“清潔代碼”一書中的“使用未經檢查的考慮”一章。 在那之后,我認為你不會遇到這種問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM