Можно ли игнорировать исключение, создаваемое при закрытии ресурса с помощью оператора try-with-resources?
Пример:
class MyResource implements AutoCloseable{
@Override
public void close() throws Exception {
throw new Exception("Could not close");
}
public void read() throws Exception{
}
}
//this method prints an exception "Could not close"
//I want to ignore it
public static void test(){
try(MyResource r = new MyResource()){
r.read();
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
Или мне следует продолжить закрытие в , наконец,
вместо этого?
public static void test2(){
MyResource r = null;
try {
r.read();
}
finally{
if(r!=null){
try {
r.close();
} catch (Exception ignore) {
}
}
}
}
Вы можете использовать шаблон декоратора, чтобы тихо закрыть ресурс:
public class QuietResource<T extends AutoCloseable> implements AutoCloseable{
T resource;
public QuietResource(T resource){
this.resource = resource;
}
public T get(){
return resource;
}
@Override
public void close() {
try {
resource.close();
}catch(Exception e){
// suppress exception
}
}
}
Я лично не фанат получающегося синтаксиса, но, возможно, это работает для вас:
public static void test(){
try(QuietResource<MyResource> qr = new QuietResource<>(new MyResource())){
MyResource r = qr.get();
r.read();
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
Вы можете добиться большего успеха, если хотите ограничиться работой с интерфейсами и использовать класс динамического прокси:
public class QuietResource<T> implements InvocationHandler {
private T resource;
@SuppressWarnings("unchecked")
public static <V extends AutoCloseable> V asQuiet(V resource){
return (V) Proxy.newProxyInstance(
resource.getClass().getClassLoader(),
resource.getClass().getInterfaces(),
new QuietResource<V>(resource));
}
public QuietResource(T resource){
this.resource = resource;
}
@Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
if(m.getName().equals("close")){
try {
return m.invoke(resource, args);
}catch(Exception e){
System.out.println("Suppressed exception with message: " + e.getCause().getMessage());
// suppress exception
return null;
}
}
return m.invoke(resource, args);
}
}
Тогда предположим, что у вас есть:
public interface MyReader extends AutoCloseable{
int read();
}
С реальным классом ресурсов:
public class MyResource implements MyReader {
public void close() throws Exception{
throw new Exception("ha!");
}
public int read(){
return 0;
}
}
Синтаксис вызова будет выглядеть следующим образом:
public static void test(){
try(MyReader r = QuietResource.asQuiet(new MyResource())){
r.read();
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
Вы можете добиться большего успеха, чем это, если вы хотите начать включать библиотеки, например AOP активаторы. Эти решения, однако, будут работать из коробки с JDK7 и без других зависимостей.