[英]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.