Programing

컴파일러 오류가없는 여러 반환 문

lottogame 2020. 11. 20. 08:23
반응형

컴파일러 오류가없는 여러 반환 문


이것은 인터뷰 질문이었습니다.

public class Demo {

    public static void main(String[] args) {
        System.out.println(foo());
    }

    static String foo() {
        try {
            return "try ...";
        } catch (Exception e) {
            return "catch ...";
        } finally {
            return "finally ..."; //got as result
        }
    }
}

내 질문은 컴파일 시간 오류가없는 이유입니다. finally블록에 return 문이 있으면 and block finally대신에 반환하도록 바인딩됩니다 . 이 코드를 옵션 으로 컴파일하려고 시도했는데 경고가 표시됩니다.trycatch-Xlint

warning: [finally] finally clause cannot complete normally

Java 언어 사양에서 허용하므로 컴파일 오류가 발생하지 않습니다. 그러나 블록에 return문을 포함하는 finally것은 일반적으로 나쁜 생각 이기 때문에 경고 메시지를 표시합니다 .

귀하의 예에서 일어나는 일은 다음과 같습니다. 블록 return명령문 try이 실행됩니다. 그러나 finally블록은 항상 실행되어 catch블록이 완료된 후에 실행되어야합니다 . 여기서 return발생하는 문은 이전 return문의 결과를 덮어 쓰므로 메서드는 두 번째 결과를 반환합니다.

마찬가지로 finally블록은 일반적으로 예외를 발생시키지 않아야합니다. 그렇기 때문에 경고가 finally블록이 정상적으로 완료되어야한다고, 즉 return예외 없이 또는 예외가 발생 해야 한다고 말하는 이유 입니다.


이것은 Java 언어 사양에 설명되어 있습니다.

§14.17

finally절의 갑작스러운 완료 return명령문에 의해 시작된 제어 전송을 방해 할 수 있습니다 .

§14.20.2

try블록 실행이 정상적으로 완료되면 finally블록이 실행되고 다음 선택 사항이 있습니다.

  • 는 IF finally블록이 정상적으로 완료 한 후 try문이 정상적으로 완료됩니다.
  • 상기 중간 finally블록이 이유에 대해 S 급격 완료 후, try문이 완료 이유로 갑자기 대 S.

try다른 이유 R로 인해 블록 실행이 갑자기 완료되면 finally블록이 실행되고 선택 사항이 있습니다.

  • 은 if finally블록은 다음, 정상적으로 완료 try이유 R.위한 문이 완료 갑자기
  • 상기 중간 finally블록이 이유에 대해 S 급격 완료 후 try갑자기 이유 S에 대한 문이 완료 (이성 R은 폐기된다).

return명령문의 1 개와 정확히 1 개만 실제로 컨트롤을 호출 코드로 반환 하므로 컴파일 시간 오류가 없습니다 .

@Hoopje에서 설명했듯이, return내에서 try또는 catch먼저 실행될 것이며, 각각의 return 문도 실행됩니다. 그러나 컨트롤을 호출 코드로 되돌리기 직전에 finally블록 을 실행합니다 . 이제 이것은 block또한 return무언가이므로이 반환은 이전 반환을 재정의합니다.


본질적으로 다음과 같습니다.

public boolean someMethod(){
        if(1 == 1){
            return true;
        }
        return false;
}

경고를 제공하지만 컴파일 오류를 제공하지 않습니다. 컴파일러는 return 문이 실행 되지 않을 가능성이있을 때만 오류를 제공합니다 .


Brilliant Question .. 내 지식에 따르면 코드에 finally 블록을 추가하면 try 및 catch 블록의 return 문이 finally로 전송됩니다. 그것이 작동하는 방법입니다.

따라서이 경우 모든 코드 라인이 실행 중이며 디버깅을 시도 할 수 있습니다. 코드 아래에서 시도한 세 블록 모두.

public class Main {

    public static void main(String[] args) {
        System.out.println(foo());
    }
    static String foo() {
        try {
            throw new Exception();
        } catch (Exception e) {
            return "catch ...";
        } finally {
            return "finally ..."; //got as result
        }
    }
}

아래 링크에서 아이디어를 얻을 수 있습니다. 복수 반품 : 어떤 것이 최종 반품 값을 설정합니까?


try, catch 및 finally 블록에 return 문이 하나만 있기 때문에 코드가 제대로 작동합니다. 도달 할 수없는 return 문이 있음을 알리는 try, catch 또는 finally 블록 중 하나에 두 개의 return 문을 쓰려고하면 컴파일 오류가 발생합니다.


(짧은 대답-대답 굵은 이탤릭체 부분읽으십시오 )

The execution flow as per the Java 8 docs. It provides you the details. You can infer execution of return statements based on the following.

A try statement with a finally block is executed by first executing the try block.

Then there is a choice:

• If execution of the try block completes normally, then the finally block is executed, and then there is a choice:

– If the finally block completes normally, then the try statement completes normally.

– If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S.

• If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:

– If the run-time type of V is assignment compatible with a catchable exception class of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed.

Then there is a choice:

› If the catch block completes normally, then the finally block is executed. Then there is a choice:

» If the finally block completes normally, then the try statement completes normally.

» If the finally block completes abruptly for any reason, then the try statement completes abruptly for the same reason.

If the catch block completes abruptly for reason R, then the finally block is executed. Then there is a choice:

» 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).

– If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed.

Then there is a choice:

› If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.

› If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).

• If execution of the try block completes abruptly for any other reason R, then the finally block is executed, and then there is a choice:

– 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).

the explanation is clear in this link- javaDoc


try running this:

it will print: 1, 2, 3 and then throw a division by zero Exception

public class Demo {
  public static void main(String[] args) {
    System.out.println(foo());
  }
  public static String print(int a){
    System.out.println(a);
    return String.valueOf(a/0);
  }
  static String foo() {
    try {
      return print(1);
    } catch (Exception e) {
      return print(2);
    } finally {
      return  print(3);
    }
  }
}

참고URL : https://stackoverflow.com/questions/30976123/multiple-return-statements-without-compiler-error

반응형