![](/img/trans.png)
[英]Why assigning a final field in a try-catch block within a static block is rejected?
[英]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.