简体   繁体   English

在构造函数中分配 try-catch 块中的最终字段

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

So, I'm trying to initialize a DatagramSocket in a constructor, and I want this field to be final , but my compiler (ie Eclipse) is giving me the following error:所以,我试图在构造函数中初始化一个DatagramSocket ,我希望这个字段是final ,但是我的编译器(即 Eclipse )给了我以下错误:

The blank final field datagramSocket may not have been initialized空白的最终字段 datagramSocket 可能尚未初始化

This is understandable.这是可以理解的。 Here's a code snippet:这是一个代码片段:

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

Now, I know there's a way to bypass this, but it requires me to create a temporary variable.现在,我知道有一种方法可以绕过它,但它需要我创建一个临时变量。 Here's a code snippet:这是一个代码片段:

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

So, I suppose my question is: is there a more elegant way of doing this, or is this something that I'll just have to live with if I want that field to be final ?所以,我想我的问题是:有没有更优雅的方式来做到这一点,或者如果我想让那个领域成为final的,我就必须忍受这种方式?

EDIT:编辑:

For those of you who are interested, here's the solution I came up with from your recommendations:对于那些感兴趣的人,这是我根据您的建议提出的解决方案:

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

Please, let me know if this is correct, or if you have any other suggestions.请让我知道这是否正确,或者如果您有任何其他建议。 I appreciate the help!感谢您的帮助!

Yes, after catching SocketException wrap it in runtime exception and rethrow it.是的,在捕获SocketException后将其包装在运行时异常中并重新抛出它。 Since your variable is final and you have encountered error during object initialization, your object is probably in incorrect state and you are guaranteed that it will remain as such.由于您的变量是final变量,并且您在 object 初始化期间遇到错误,因此您的 object 可能是不正确的 state 并且您可以保证它会保持原样。

Logging the exception isn't probably enough for exception handling and hiding SocketException hides the fact that the object is invalid and allows you to continue, risking NullPointerException or others.记录异常可能不足以进行异常处理和隐藏SocketException隐藏了 object 无效的事实,并允许您继续,冒着NullPointerException或其他风险。

If you really want to create such a faulty object, your suggestion is fine, just use another method:如果你真的想制造这样一个故障的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...
        }
 }

As for returning null : consider subclassing DatagramSocket and creating:至于返回null :考虑继承DatagramSocket并创建:

  • NoOpDatagramSocket

  • NullDatagramSocket

  • BrokenDatagramSocket

  • MemoryDatagramSocket

  • ...you get the idea:-) ...你明白了:-)

PS: Why the synchronized ? PS:为什么要synchronized

PS2: The comment // Log error right before logger.error() isn't adding much value, don't you think? PS2:在logger.error()之前的注释// Log error并没有增加太多价值,你不觉得吗?

A possible alternative is make your constructor throw SocketException.一种可能的替代方法是让您的构造函数抛出 SocketException。 This will get rid of the need for the try-catch block that forces you to use the temporary variable.这将消除强制您使用临时变量的 try-catch 块的需要。

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

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