【发布时间】:2015-11-11 04:22:27
【问题描述】:
我有一些丑陋的代码,想重构它:
public class UdpTransport extends AbstractLayer<byte[]> {
private final DatagramSocket socket;
private final InetAddress address;
private final int port;
/* boolean dead is provided by superclass */
public UdpTransport(String host, int port) {
this.port = port;
InetAddress tmp_address = null;
try {
tmp_address = InetAddress.getByName(host);
} catch (UnknownHostException e) {
e.printStackTrace();
dead = true;
socket = null;
address = null;
return;
}
address = tmp_address;
DatagramSocket tmp_socket = null;
try {
tmp_socket = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
dead = true;
socket = null;
return;
}
socket = tmp_socket;
}
...
导致丑陋的问题是final 成员之间的交互和捕获的异常。如果可能的话,我想保留成员final。
我想按如下方式编写代码,但 Java 编译器无法分析控制流 - 不可能再次分配 address,因为第一次尝试的分配必须抛出以获得控制权到达catch 子句。
public UdpTransport(String host, int port) {
this.port = port;
try {
address = InetAddress.getByName(host);
} catch (UnknownHostException e) {
e.printStackTrace();
dead = true;
address = null; // can only have reached here if exception was thrown
socket = null;
return;
}
...
Error:(27, 13) error: variable address might already have been assigned
有什么建议吗?
附:我有一个约束,即构造函数不会抛出 - 否则这一切都很容易。
【问题讨论】:
-
有没有想过可以使用非final而不是使用final实例变量?如果您想确保类外的不变性,请在 getter 中返回防御性副本。
-
socket创建失败是否需要
address == null? -
为什么你不能有另一个
tmp_address并在最后分配address = tmp_address? -
构造函数通常不应捕获异常。如果无法正确构造对象,则对应用程序没有任何用处。
-
从实践的角度来看,这与构造函数无关。如果您无法处理异常并修复它,那么让它冒泡。当然不要吞下它并打印堆栈跟踪。
标签: java constructor checked-exceptions