在构造函数内的 try-catch 块中分配最终字段
因此,我试图在构造函数中初始化 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;
}
}
请告诉我这是否正确,或者您是否有任何其他建议。我很感激你的帮助!
So, I'm trying to initialize a DatagramSocket
in a constructor, and I want this field to be final
, but my compiler (i.e. Eclipse) is giving me the following error:
The blank final field datagramSocket
may not have been initialized
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
?
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,在捕获 SocketException 后,将其包装在运行时异常中并重新抛出它。由于您的变量是
final
并且您在对象初始化期间遇到了错误,因此您的对象可能处于不正确的状态,并且您可以保证它将保持原样。记录异常可能不足以进行异常处理,而隐藏 SocketException 隐藏了对象无效的事实并允许您继续,从而冒着 NullPointerException 或其他风险。
如果你真的想创建这样一个错误的对象,你的建议很好,只需使用另一种方法:
至于返回
null
:考虑子类化DatagramSocket
并创建:<代码>NoOpDatagramSocket
NullDatagramSocket
BrokenDatagramSocket< /code>
MemoryDatagramSocket
...你明白了:- )
PS:为什么要
同步
?PS2:
logger.error()
之前的注释// Log error
并没有增加太多价值,你不觉得吗?Yes, after catching
SocketException
wrap it in runtime exception and rethrow it. Since your variable isfinal
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.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, riskingNullPointerException
or others.If you really want to create such a faulty object, your suggestion is fine, just use another method:
As for returning
null
: consider subclassingDatagramSocket
and creating:NoOpDatagramSocket
NullDatagramSocket
BrokenDatagramSocket
MemoryDatagramSocket
...you get the idea :-)
P.S.: Why the
synchronized
?P.S.2: The comment
// Log error
right beforelogger.error()
isn't adding much value, don't you think?一种可能的替代方法是让构造函数抛出 SocketException。这将消除对强制您使用临时变量的 try-catch 块的需要。
A possible alternative is make your constructor throw SocketException. This will get rid of the need for the try-catch block that forces you to use the temporary variable.