簡體   English   中英

在構造函數中分配 try-catch 塊中的最終字段

[英]Assigning a final field in a try-catch block within a constructor

所以,我試圖在構造函數中初始化一個DatagramSocket ,我希望這個字段是final ,但是我的編譯器(即 Eclipse )給了我以下錯誤:

空白的最終字段 datagramSocket 可能尚未初始化

這是可以理解的。 這是一個代碼片段:

    public class Foo
    {
        private final int DEFAULT_UDPLISTENPORT = 49400;
        private final DatagramSocket datagramSocket;

        public Foo()
        {
            synchronized(this)
            {
                try
                {
                    datagramSocket = new DatagramSocket(DEFAULT_UDPLISTENPORT);
                }
                catch (SocketException e)
                {
                    // Log error
                    logger.error("Trouble opening UDP port: ", e);
                }
            }
        }
    }

現在,我知道有一種方法可以繞過它,但它需要我創建一個臨時變量。 這是一個代碼片段:

    public class Foo
    {
        private final int DEFAULT_UDPLISTENPORT = 49400;
        private final DatagramSocket datagramSocket;

        public Foo()
        {
            synchronized(this)
            {
                DatagramSocket tempSocket = null;
                try
                {
                    tempSocket = new DatagramSocket(DEFAULT_UDPLISTENPORT);
                }
                catch (SocketException e)
                {
                    // Log error
                    logger.error("Trouble opening UDP port: ", e);
                }

                datagramSocket = tempSocket;
            }
        }
    }

所以,我想我的問題是:有沒有更優雅的方式來做到這一點,或者如果我想讓那個領域成為final的,我就必須忍受這種方式?

編輯:

對於那些感興趣的人,這是我根據您的建議提出的解決方案:

public class Foo
{
    private static final Foo INSTANCE;
    static
    {
        try
        {
            INSTANCE = new Foo();
        }
        catch (SocketException e)
        {
            throw new ExceptionInInitializerError(e);
        }
    }
    private final int DEFAULT_UDPLISTENPORT = 49400;
    private final DatagramSocket datagramSocket;

    public Foo() throws SocketException
    {
        synchronized (this)
        {
            datagramSocket = new DatagramSocket(DEFAULT_UDPLISTENPORT);
        }
    }

    public static Foo getInstance()
    {
        return INSTANCE;
    }
}

請讓我知道這是否正確,或者如果您有任何其他建議。 感謝您的幫助!

是的,在捕獲SocketException后將其包裝在運行時異常中並重新拋出它。 由於您的變量是final變量,並且您在 object 初始化期間遇到錯誤,因此您的 object 可能是不正確的 state 並且您可以保證它會保持原樣。

記錄異常可能不足以進行異常處理和隱藏SocketException隱藏了 object 無效的事實,並允許您繼續,冒着NullPointerException或其他風險。

如果你真的想制造這樣一個故障的object,你的建議沒問題,換一種方法就好了:

public Foo()
    {
        synchronized(this)
        {
            datagramSocket = createSocket();
        }
    }

private DatagramSocket createSocket() {
        try
        {
            return new DatagramSocket(DEFAULT_UDPLISTENPORT);
        }
        catch (SocketException e)
        {
            logger.error("Trouble opening UDP port: ", e);
            return null;  //I beg you, don't return null here...
        }
 }

至於返回null :考慮繼承DatagramSocket並創建:

  • NoOpDatagramSocket

  • NullDatagramSocket

  • BrokenDatagramSocket

  • MemoryDatagramSocket

  • ...你明白了:-)

PS:為什么要synchronized

PS2:在logger.error()之前的注釋// Log error並沒有增加太多價值,你不覺得嗎?

一種可能的替代方法是讓您的構造函數拋出 SocketException。 這將消除強制您使用臨時變量的 try-catch 塊的需要。

暫無
暫無

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

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