문제

은 거기에 우아하게 처리하는 방법에는 예외에 던져 finally block?

예를 들어:

try {
  // Use the resource.
}
catch( Exception ex ) {
  // Problem with the resource.
}
finally {
   try{
     resource.close();
   }
   catch( Exception ex ) {
     // Could not close the resource?
   }
}

어떻게 피할 try/catchfinally block?

도움이 되었습니까?

해결책

나는 보통 이렇게한다 :

try {
  // Use the resource.
} catch( Exception ex ) {
  // Problem with the resource.
} finally {
  // Put away the resource.
  closeQuietly( resource );
}

다른 곳 :

protected void closeQuietly( Resource resource ) {
  try {
    if (resource != null) {
      resource.close();
    }
  } catch( Exception ex ) {
    log( "Exception during Resource.close()", ex );
  }
}

다른 팁

나는 일반적으로 하나를 사용합니다 closeQuietly 방법 org.apache.commons.io.IOUtils:

public static void closeQuietly(OutputStream output) {
    try {
        if (output != null) {
            output.close();
        }
    } catch (IOException ioe) {
        // ignore
    }
}

Java 7을 사용하는 경우 resource 구현 AutoClosable, 당신은 이것을 할 수 있습니다 (입력 스트림을 예로 사용) :

try (InputStream resource = getInputStream()) {
  // Use the resource.
}
catch( Exception ex ) {
  // Problem with the resource.
}

틀림없이 조금만,어쩌면 당신을 시키는 예외는 거대하고 로그인할 수 없도 내에서 당신의 방법(예:기 때문에 그리고 당신은 오히려 부르는 코드 예외 처리 및 로깅):

Resource resource = null;
boolean isSuccess = false;
try {
    resource = Resource.create();
    resource.use();
    // Following line will only run if nothing above threw an exception.
    isSuccess = true;
} finally {
    if (resource != null) {
        if (isSuccess) {
            // let close throw the exception so it isn't swallowed.
            resource.close();
        } else {
            try {
                resource.close();
            } catch (ResourceException ignore) {
                // Just swallow this one because you don't want it 
                // to replace the one that came first (thrown above).
            }
        }
    }
}

업데이트:나는 이것으로 더 많은 것을 발견한 블로그 포스팅에서는 사람은 분명히 생각이 나보다 더: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html 그는 한 단계 더 나아가 두 가지 예외 중 하나로,나는 유용한 것으로 볼 수 있습니다 경우가 있습니다.

Java 7 기준으로 더 이상 자원을 명시 적으로 폐쇄 할 필요가 없습니다. 마지막으로 대신 사용할 수 있습니다 노력하다-자원이있는 구문. Try-With-resources 문은 하나 이상의 리소스를 선언하는 시도 문입니다. 리소스는 프로그램이 완료된 후에 닫아야하는 객체입니다. Try-With-resources 문은 각 리소스가 명세서 끝에 닫히도록합니다. java.io.closeable을 구현하는 모든 객체를 포함하는 java.lang.autocloseable을 구현하는 모든 객체는 리소스로 사용할 수 있습니다.

다음 코드를 가정하십시오.

try( Connection con = null;
     Statement stmt = con.createStatement();
     Result rs= stmt.executeQuery(QUERY);)
{  
     count = rs.getInt(1);
}

예외가 발생하면 닫다 이 세 가지 리소스 각각에 대한 방법은 그들이 만들어진 순서대로 호출됩니다. 이는 닫기 메소드가 resultSetm에 대해 먼저 호출 된 다음 문과 연결 객체의 끝에 호출됩니다.

가까운 방법이 자동으로 호출 될 때 발생하는 예외가 억제된다는 것을 아는 것도 중요합니다. 이러한 억제 된 예외는 검색 할 수 있습니다 getsuppressed () 에 정의 된 메소드 던질 수 있습니다 수업.

원천: https://docs.oracle.com/javase/tutorial/estential/exceptions/tryresourceclose.html

'마지막으로'블록에서 발생하는 예외를 무시하는 것은 일반적으로 나쁜 생각 그 예외가 무엇인지, 어떤 조건을 나타내는 지 알지 않는 한. 정상적으로 try/finally 사용 패턴, try 블록은 물건을 상태로 배치합니다. 외부 코드는 기대하지 않을 것입니다. finally 블록은 외부 코드가 기대하는 것들로 이러한 것들의 상태를 복원합니다. 예외를 포착하는 외부 코드는 일반적으로 예외에도 불구하고 모든 것이 normal 상태. 예를 들어, 일부 코드가 트랜잭션을 시작한 다음 두 개의 레코드를 추가하려고한다고 가정합니다. "마지막으로"블록은 "커밋되지 않은 경우 롤백"작업을 수행합니다. 발신자는 두 번째 "ADD"작업을 실행하는 동안 예외가 발생할 수 있도록 준비 될 수 있으며, 그러한 예외를 포착하면 데이터베이스가 상태에있을 것으로 예상 할 수 있습니다. 그러나 롤백 중에 두 번째 예외가 발생하면 발신자가 데이터베이스 상태에 대해 가정을하는 경우 나쁜 일이 발생할 수 있습니다. 롤백 실패는 a를 나타냅니다 주요한 위기-단순한 "레코드를 추가하지 못한"예외를 기대하는 코드에 의해 잡히지 말아야 할 것입니다.

저의 개인적인 성향은 마침내 메소드 잡기 예외를 제외하고 "CleanupFailedException"으로 래핑하는 것입니다. 그러한 실패는 주요 문제를 나타내며 그러한 예외는 가볍게 잡아서는 안된다는 것을 인식합니다.

두 가지 예외가 두 가지 다른 클래스 인 경우 하나의 솔루션

try {
    ...
    }
catch(package1.Exception err)
   {
    ...
   }
catch(package2.Exception err)
   {
   ...
   }
finally
  {
  }

그러나 때로는이 두 번째 시도를 피할 수 없습니다. 예를 들어 스트림을 닫는 것

InputStream in=null;
try
 {
 in= new FileInputStream("File.txt");
 (..)// do something that might throw an exception during the analysis of the file, e.g. a SQL error
 }
catch(SQLException err)
 {
 //handle exception
 }
finally
 {
 //at the end, we close the file
 if(in!=null) try { in.close();} catch(IOException err) { /* ignore */ }
 }

추가 블록을 피하고 싶은 이유는 무엇입니까? 마지막으로 블록에는 예외가 발생할 수있는 "정상"작업이 포함되어 있으므로 최종 블록이 완전히 실행되기를 원합니다. 예외를 포착해야합니다.

마침내 블록이 예외를 던질 것으로 예상되지 않고 예외를 처리하는 방법을 모르면 (스택 트레이스를 덤프하는 것만) 예외가 통화 스택을 기포하게하십시오 (마침내 Try-Catch를 제거하십시오. 차단하다).

타이핑을 줄이려면 "글로벌"외부 트리 캐치 블록을 구현할 수 있습니다.

try {
    try {
        ...
    } catch (Exception ex) {
        ...
    } finally {
        ...
    }

    try {
        ...
    } catch (Exception ex) {
        ...
    } finally {
        ...
    }

    try {
        ...
    } catch (Exception ex) {
        ...
    } finally {
        ...
    }
} catch (Exception ex) {
    ...
}

많은 고려 후 다음 코드를 가장 잘 찾습니다.

MyResource resource = null;
try {
    resource = new MyResource();
    resource.doSomethingFancy();
    resource.close(); 
    resource = null;  
} finally {
    closeQuietly(resource)
}

void closeQuietly(MyResource a) {
    if (a!=null)
        try {
             a.close();
        } catch (Exception e) {
             //ignore
        }
}

해당 코드는 다음을 보장합니다.

  1. 코드가 완료되면 리소스가 해제됩니다
  2. 자원을 폐쇄 할 때 발생하는 예외는 처리하지 않고 소비되지 않습니다.
  3. 코드는 리소스를 두 번 닫으려고 시도하지 않으며 불필요한 예외는 생성되지 않습니다.

당신이 시작할 오류 조건을 피하기 위해 테스트 해야하는 경우.

try{...}
catch(NullArgumentException nae){...}
finally
{
  //or if resource had some useful function that tells you its open use that
  if (resource != null) 
  {
      resource.Close();
      resource = null;//just to be explicit about it was closed
  }
}

또한 회복 할 수있는 예외 만 잡을 수있을 것입니다. 복구 할 수 없다면 프로그램의 최상위 레벨로 전파하십시오. 이미했던 것처럼 코드를 테스트 캐치 블록으로 코드를 둘러싼 오류 조건을 테스트 할 수없는 경우 (여전히 구체적이고 예상되는 오류를 포착하는 것이 좋습니다).

이것을 다른 방법으로 리팩토링 할 수 있습니다 ...

public void RealDoSuff()
{
   try
   { DoStuff(); }
   catch
   { // resource.close failed or something really weird is going on 
     // like an OutOfMemoryException 
   }
}

private void DoStuff() 
{
  try 
  {}
  catch
  {
  }
  finally 
  {
    if (resource != null) 
    {
      resource.close(); 
    }
  }
}

나는 보통 이것을한다 :

MyResource r = null;
try { 
   // use resource
} finally {   
    if( r != null ) try { 
        r.close(); 
    } catch( ThatSpecificExceptionOnClose teoc ){}
}

이론적 근거 : 자원을 완료하고 내가 가진 유일한 문제는 그것에 대해 할 수있는 일이 많지 않습니다. 어쨌든 자원을 마친다면 전체 스레드를 죽이는 것은 의미가 없습니다.

이것은 적어도 나에게 적어도 확인 된 예외를 무시하는 것이 안전합니다.

오늘날까지 나는이 관용구를 사용하는 데 아무런 문제가 없었습니다.

try {
    final Resource resource = acquire();
    try {
        use(resource);
    } finally {
        resource.release();
    }
} catch (ResourceException exx) {
    ... sensible code ...
}

작업이 완료되었습니다. 널 테스트가 없습니다. 단일 캐치, 획득 및 릴리스 예외가 포함됩니다. 물론 관용구 주변의 실행을 사용할 수 있으며 각 리소스 유형에 대해 한 번만 작성해야합니다.

바꾸다 Resource ~에서 베스트 답변 에게 Closeable

스트림 구현 Closeable 따라서 모든 스트림의 방법을 재사용 할 수 있습니다

protected void closeQuietly(Closeable resource) {
    if (resource == null) 
        return;
    try {
        resource.close();
    } catch (IOException e) {
        //log the exception
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top