2013-12-18 8 views
12

czytałem o try-with-zasobu JDK7 i gdy myślałem o modernizacji mojej aplikacji do uruchomienia z JDK7 I w obliczu tego problemu ..Wyjątek wychodzi Close() w try-with-zasobu

Podczas korzystania z BufferedReader, na przykład, zapis rzuca wyjątek IOException i zamyka rzutuje IOException .. w bloku catch Jestem zaniepokojony IOException wyrzucony przez napis .. ale nie obchodzi mnie dużo o tym, rzucił przez blisko ..

sam problem z połączeniami baz .. i każdy inny zasób ..

Jako przykład Utworzyłem auto zamykany resou RCE:

public class AutoCloseableExample implements AutoCloseable { 

    public AutoCloseableExample() throws IOException{ 
     throw new IOException(); 
    } 

    @Override 
    public void close() throws IOException { 
     throw new IOException("An Exception During Close"); 
    } 

} 

Teraz podczas używania go:

public class AutoCloseTest { 

    public static void main(String[] args) throws Exception { 
     try (AutoCloseableExample example = new AutoCloseableExample()) { 
      System.out.println(example); 

      throw new IOException("An Exception During Read"); 
     } catch (Exception x) { 
      System.out.println(x.getMessage()); 
     } 
    } 

} 

jak mogę odróżnić takich wyjątków, bez konieczności tworzenia otoki dla klas takich jak BufferedReader?

W większości przypadków umieszczam zasób w próbie/haczyku wewnątrz bloku końcowego, nie troszcząc się zbytnio o jego obsługę.

+0

Gdzie jest kod? –

+0

Mam na myśli ogólną koncepcję. Tak czy inaczej .. Dodam fragment kodu teraz .. –

Odpowiedz

10

Pozwala rozważyć klasę:

public class Resource implements AutoCloseable { 

    public Resource() throws Exception { 
     throw new Exception("Exception from constructor"); 
    } 

    public void doSomething() throws Exception { 
     throw new Exception("Exception from method"); 
    } 

    @Override 
    public void close() throws Exception { 
     throw new Exception("Exception from closeable"); 
    } 
} 

i try-with-Blok zasobów:

try(Resource r = new Resource()) { 
     r.doSomething(); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 

1. Wszystkie 3 rzucać oświadczenia włączone.

Wiadomość "Wyjątek od konstruktora" zostanie wydrukowana, a wyjątek wygenerowany przez konstruktora zostanie usunięty z , co oznacza, że ​​nie można go przechwycić.

2. Rzut w konstruktorze został usunięty.

Teraz ślad stosu wyświetli "wyjątek od metody" i "pominięty: wyjątek z zamknięcia" poniżej. Tutaj także nie można przechwycić wyłączonego wyjątku, rzucanego przez metodę close, ale zostaniesz nofitowany o wyłączonym wyjątku.

. Rzuty z konstruktora i metody są usuwane.

Jak już zapewne zgadłeś, zostanie wydrukowany komunikat "Wyjątek z zamknięcia".

Ważna wskazówka: We wszystkich powyższych sytuacjach rzeczywiście jesteś połowu wszystkie wyjątki, bez względu na to, gdzie zostały one throwed. Więc jeśli użyjesz bloku try-with-resource, nie musisz owijać bloku innym try-catch, to po prostu bezużyteczne.

Nadzieja to pomaga :)

+0

Dziękuję za Twój wkład .. Całkowicie rozumiem to .. problem, który myślę, to jak odróżnić wyjątki wyrzucone z metody takie jak doSomething() i metoda close(), ponieważ oba rzucają ten sam typ wyjątku .. doSomething() zasługuje na haczyk, ponieważ coś w przepływie występuje .. podczas gdy wyjątek wyrzucony z close() nie jest tak wiele W większości przypadków jest to ważne i sprawia, że ​​jestem zdezorientowany. –

+2

OK, teraz widzę, o co ci chodzi. Jeśli chcesz odróżnić wyjątki od kodu, możesz uzyskać nazwę metody wyjątku przez 'ex.getStackTrace() [0] .getMethodName()'. Jeśli nie, możesz po prostu wydrukować ślad stosu i przeczytać go. –

0

Proponuję za pomocą znacznika, jak w poniższym przykładzie:

static String getData() throws IOException { 
    boolean isTryCompleted = false; 
    String theData = null; 
    try (MyResource br = new MyResource();) { 

     theData = br.getData(); 
     isTryCompleted = true; 

    } catch(IOException e) { 
     if (!isTryCompleted) 
      throw e; 
     // else it's a close exception and it can be ignored 
    } 

    return theData; 
} 

źródło: Close resource quietly using try-with-resources