所以,我试图在构造函数中初始化一个 DatagramSocket
,我希望这个字段是 final
,但是我的编译器(即 Eclipse)给了我以下错误:
The blank final field datagramSocket may not have been initialized
这是可以理解的。这是一个代码片段:
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
并且您在对象初始化期间遇到错误,您的对象可能处于不正确的状态并且您保证它将保持原样。
记录异常可能不足以进行异常处理,隐藏 SocketException
会隐藏对象无效的事实并允许您继续,冒着 NullPointerException
或其他风险。
如果你真的想创建这样一个错误的对象,你的建议很好,只需使用另一种方法:
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
...你明白了:-)
附言:为什么要同步
?
P.S.2:logger.error()
之前的注释 //Log error
没有增加太多值(value),你不觉得吗?
关于java - 在构造函数中的 try-catch block 中分配最终字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5858250/