2010-04-08 10 views
8

Java가 try 블록에서 값을 설정 한 후 catch 블록의 최종 변수에 값을 할당하지 못하게하는 이유는 무엇이든지 예외의 경우 최종 값을 기록 할 수 있습니다. 여기 Java에서 예외가 발생할 경우 최종 변수에 할당

문제를 보여줍니다 예입니다

public class FooBar { 

    private final int foo; 

    private FooBar() { 
     try { 
      int x = bla(); 
      foo = x; // In case of an exception this line is never reached 
     } catch (Exception ex) { 
      foo = 0; // But the compiler complains 
        // that foo might have been initialized 
     } 
    } 

    private int bla() { // You can use any of the lines below, neither works 
     // throw new RuntimeException(); 
     return 0; 
    } 
} 

문제는 해결하려면하지 어렵습니다,하지만 난 컴파일러는이 동의하지 않는 이유를 이해하고 싶습니다.

미리 감사드립니다.

+2

글쎄, 일반적인 '예외'를 ​​잡는다면, 예외를 던질 'foo = x'이후/후에 '발생'할 수 있습니까? 어쩌면 컴파일러가 "안전하게 사용하고 있습니까?" – FromCanada

+0

그게 질문입니다. 하지만 할당이 예외를 던져 결과를 변수에 쓸 수 있다는 것은 정말로 의심 스럽습니다. – Alfonso

+2

"예외가 발생하는 경우이 행에 도달하지 못했습니다."컴파일러가 그 세부 수준에 대한 의도를 알지 못하는 것 같습니다. 그래서 그것이 보이는 것은 foo가 두 번 배정되는 것입니다. 아마도 x가 궁극적으로 불필요하기 때문에 컴파일러가 코드를 foo = bla()로 최적화 할 수 있습니다. 그냥 추측. – greim

답변

7
try { 
    int x = bla(); 
    foo = x; // In case of an exception this line is never reached 
} catch (Exception ex) { 
    foo = 0; // But the compiler complains 
      // that foo might have been initialized 
} 

이유입니다. 그것이 사실이 분명하지만, 고려 곳이 예는 특별한 경우이다 :

try { 
    int x = bla(); 
    foo = x; // In case of an exception this line is never reached...or is it? 
    callAnotherFunctionThatThrowsAnException(); // Now what? 
} catch (Exception ex) { 
    foo = 0; // But the compiler complains 
      // that foo might have been initialized, 
      // and now it is correct. 
} 

이 엄청난 작업을 것 같은 아주 특별한 경우를 처리하기 위해 컴파일러를 작성하려면 - 그들 중 아주 많은 가능성이있다.

+0

그게 문제라고 생각합니다. 과제는 부작용이있을 수있는 진술 이후 여야합니다. 내 생각에는 너무 어렵지 않을 것입니다.하지만 다른 한편으로는 손쉽게 해결할 수 있습니다 (약간 추한 경우). – Alfonso

0

던져지는 방법에 대해 Error? 컴파일러는 foo이 initalized되기 전에 예외는 발생 될 수 있음을 추론 할 수 없기 때문에

+0

맞아, 대신에 Throwable 잡기. 그것이 당신을 시키면. – bmargulies

+0

이것은 try-catch 블록 밖으로 전파되어 new FooBar();의 호출자에서 예외가 발생합니다. 따라서 최종 변수는 절대로 기록되지 않습니다. 하지만 필자의 경우 컴파일러는 변수가 두 번 쓰여질 수 있다고 불평하고있다. – Alfonso

+0

네, 맞습니다. 나는 그 질문을 잘못 해석했다. 나는 또한 실제로 이것에 짜증이났다. – lexicore

2

팬트가 되려면 Thread.stop(Throwable)은 try 블록 할당 직후 예외를 throw 할 수 있습니다.

그러나 명확한 지정 및 관련 용어가있는 규칙은 충분히 복잡합니다. JLS를 확인하십시오. 규칙을 더 추가하려고하면 언어가 복잡해지며 큰 이익을 얻지 못합니다.

+0

와우, 나는 Thread.stop (Throwable)에 대해 몰랐다. 이것은 전체 JDK에서 가장 나쁜 방법이어야합니다 ... – Alfonso

+0

+1은 JLS를 언급합니다. 이것은 컴파일러 구현의 단점이 아닙니다. – Antimony

관련 문제