Java 9: Effectively final variables in try-with-resources
Try with resources, first introduced in Java 7, is a Loan Pattern implementation baked in the language which enables us to borrow a AutoCloseable resource, mess with it as we wish and in the meanwhile, not to worry about freeing the resource; because it’s automatically being taken care of by the compiler. Before this feature being rolled out, the common idiom to use a resource was kinda like the following:
InetSocketAddress birthPort = new InetSocketAddress(1989);
DatagramChannel udpServer = DatagramChannel.open().bind(birthPort);
try {
udpServer.receive(buffer);
// Process the packet
} catch (Exception e) {
// handle the exception
} finally {
if (udpServer != null) {
try {
udpServer.close();
} catch (Exception ignored) {}
}
}
Try with resources reduces the preceding code to:
InetSocketAddress birthPort = new InetSocketAddress(1989);
try(DatagramChannel udpServer = DatagramChannel.open().bind(birthPort)) {
udpServer.receive(buffer);
// Process the packet
} catch (Exception e) {
// handle the exception
}
There is no need to explicitly free the borrowed resource, which is nice, but the resource declaration is a bit ugly and it’s even more uglier if we try to manage multiple resources:
InetSocketAddress birthPort = new InetSocketAddress(1989);
try (DatagramChannel udpServer = DatagramChannel.open().bind(birthPort);
Selector selector = Selector.open()) {
// go non-blocking and register channel with selector
udpServer.receive(buffer);
// Process the packet
} catch (Exception e) {
// handle the exception
}
The problem is, In Java 7, the resources to be managed by a try-with-resources must be fresh variables declared like:
try (Resource resource = ...)
In Java 9, the try-with-resources statement refined in a way that it can accept final
and effectively final
variables. So in Java 9 you can write:
InetSocketAddress birthPort = new InetSocketAddress(1989);
DatagramChannel udpServer = DatagramChannel.open().bind(birthPort);
Selector selector = Selector.open();
try (udpServer;selector) {
// go non-blocking and register channel with selector
udpServer.receive(buffer);
// Process the packet
} catch (Exception e) {
// handle the exception
}