Java의 최종 블록에서 돌아오다
최근에 Java에서 최종적으로 return 스테이트먼트를 블록에 넣을 수 있다는 것을 알고 놀랐습니다.
많은 사람들이 'Don't return in a final clause'에서 설명한 것처럼 그것을 하는 것이 나쁘다고 생각하는 것 같다.좀 더 깊이 들어가 보니 'Java's return does always's not always'라는 글도 있었습니다.이 글에서는 최종적으로 블록 내의 다른 유형의 흐름 제어의 매우 끔찍한 예를 몇 가지 볼 수 있습니다.
그래서 질문입니다만, 최종적으로 블록내의 리턴 스테이트먼트(또는 다른 플로우 제어)에 의해서, 보다 좋은/가독성이 높은 코드가 생성되는 예를 들면, 누구라도 있습니까?
몇 년 전 이 문제로 인해 발생한 버그를 추적하는 데 정말 어려움을 겪었습니다.코드는 다음과 같았습니다.
Object problemMethod() {
Object rtn = null;
try {
rtn = somethingThatThrewAnException();
}
finally {
doSomeCleanup();
return rtn;
}
}
예외는 다른 코드에서 느려졌습니다., 되고, 되고 있다.somethingThatThrewAnException()
하지만 과거로 .problemMethod()
오랜 시간 검토한 끝에 반품 방법을 찾아냈습니다.마지막 블록의 반환 방식은 기본적으로 시행 블록에서 발생한 예외가 포착되지 않았더라도 전파되지 않도록 하는 것이었습니다.
다른 사람들이 말했듯이 자바 사양에 따라 최종 블록에서 돌아오는 것은 합법이지만, 그것은 나쁜 일이며 해서는 안 됩니다.
제시된 예는 최종적으로 flow-control을 사용하지 않는 충분한 이유입니다.
「더 좋은」예가 있는 경우라도, 나중에 코드를 관리할 필요가 있는 개발자와 그 미묘한 점을 모르는 개발자를 생각해 주세요.그 불쌍한 개발자는 당신일 수도 있어요.
-Xlint:finally를 사용하면 javac이 반환 경고를 표시합니다.원래 javac은 경고를 내보내지 않았습니다.코드에 문제가 있는 경우 컴파일에 실패합니다.불행하게도 역호환성은 예상치 못한 기발한 어리석음을 막을 수 없다는 것을 의미한다.
최종 블록에서 예외를 던질 수 있지만, 이 경우 표시되는 행동은 거의 확실히 원하는 것입니다.
제어 구조를 추가하고 마지막으로 {}개의 블록으로 되돌리는 것은 사실상 모든 개발 언어에 퍼져 있는 "할 수 있기 때문에" 남용의 또 다른 예에 불과합니다.Jason이 이것이 쉽게 유지보수의 악몽이 될 수 있다고 제안한 것은 옳았습니다. 즉, 함수로부터의 조기 반환에 반대하는 주장은 이 "늦은 반환" 사례에 더 많이 적용됩니다.
마지막으로 블록은 한 가지 목적을 위해 존재하며, 선행하는 모든 코드에서 무슨 일이 일어나더라도 완전히 정리할 수 있습니다.이것은 주로 파일 포인터, 데이터베이스 연결 등을 닫거나 해제하는 것이지만, 맞춤형 감사에서 추가라고 말하기 위해 확장되는 것을 볼 수 있었습니다.
함수 반환에 영향을 미치는 모든 항목은 try{} 블록에 있어야 합니다.외부 상태를 체크하고 시간이 걸리는 작업을 수행한 후 무효가 되었을 때 해당 상태를 다시 체크하는 방법이 있더라도 try{} 내에서 두 번째 체크를 원할 것입니다.이 방법이 최종적으로 내부에 배치되어 장시간 작업이 실패하면 그 상태를 불필요하게 두 번째 체크하게 됩니다.
간단한 그루비 테스트:
public class Instance {
List<String> runningThreads = new ArrayList<String>()
void test(boolean returnInFinally) {
println "\ntest(returnInFinally: $returnInFinally)"
println "--------------------------------------------------------------------------"
println "before execute"
String result = execute(returnInFinally, false)
println "after execute -> result: " + result
println "--------------------------------------------------------------------------"
println "before execute"
try {
result = execute(returnInFinally, true)
println "after execute -> result: " + result
} catch (Exception ex) {
println "execute threw exception: " + ex.getMessage()
}
println "--------------------------------------------------------------------------\n"
}
String execute(boolean returnInFinally, boolean throwError) {
String thread = Thread.currentThread().getName()
println "...execute(returnInFinally: $returnInFinally, throwError: $throwError) - thread: $thread"
runningThreads.add(thread)
try {
if (throwError) {
println "...error in execute, throw exception"
throw new Exception("as you liked :-)")
}
println "...return 'OK' from execute"
return "OK"
} finally {
println "...pass finally block"
if (returnInFinally) return "return value from FINALLY ^^"
// runningThreads.remove(thread)
}
}
}
Instance instance = new Instance()
instance.test(false)
instance.test(true)
출력:
test(returnInFinally: false)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: OK
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
execute threw exception: as you liked :-)
-----------------------------------------------------------------------------
test(returnInFinally: true)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------
질문:.
나에게 한 가지 흥미로운 점은 그루비가 암묵적인 수익에 어떻게 대처하는지 보는 것이었다.Groovy에서는 단순히 마지막에 값을 남기기만 하면(반환하지 않고) 메서드에서 "반환"할 수 있습니다.실행 코멘트를 해제하면 어떤 일이 일어날까요?마지막 문의 threads.remove(..) 행 - 일반 반환값("OK")을 덮어쓰고 예외를 적용합니까?
내부에서 돌아오다finally
블록이 원인이 되다exceptions
사라지다
finally 블록 내에 return 문이 있으면 try 블록 또는 catch 블록에 느려질 수 있는 예외가 모두 폐기됩니다.
Java Language Specification(Java 언어 사양)에 따르면:
다른 이유 R에 의해 try block 실행이 갑자기 완료되면 최종적으로 block이 실행되어 다음 중 하나를 선택할 수 있습니다.
If the finally block completes normally, then the try statement completes abruptly for reason R. If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
주의: JLS 14.17에 따라 반환문은 항상 갑자기 완료됩니다.
언급URL : https://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java
'programing' 카테고리의 다른 글
암묵적 유형 승격 규칙 (0) | 2022.08.23 |
---|---|
hashCode에 소수점을 사용하는 이유는 무엇입니까? (0) | 2022.08.23 |
Passport를 사용하여 API 호출에서 laravel_token을 새로 고치는 방법 (0) | 2022.08.23 |
@RequestParam in Spring MVC에서 옵션 파라미터 처리 (0) | 2022.08.23 |
Absolute 파일 경로를 포함하는 문자열에서 파일 이름을 가져오려면 어떻게 해야 합니까? (0) | 2022.08.16 |