java 자바 - 컴파일러 오류가없는 여러 개의 return 문




메소드 탈출 (8)

다음을 실행 해보십시오 :

그것은 인쇄 할 것입니다 : 1, 2, 3 그리고 나서 0으로 나눗셈을 던져 예외

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);
    }
  }
}

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

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 문이 있으면 trycatch 블록 대신 finally 에서 반환하도록 바인딩됩니다. -Xlint 옵션을 사용하여이 코드를 컴파일하려고 시도했지만 경고를 표시합니다.

warning: [finally] finally clause cannot complete normally

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

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

경고를 표시하지만 컴파일 오류는 발생하지 않습니다. 컴파일러는 return 문이 실행 되지 않을 때만 오류를 발생시킵니다.


return 문 중 1 개와 정확히 1 개만 실제로 컨트롤을 호출 코드로 반환하기 때문에 컴파일 타임 오류가 없습니다.

@Hoopje에 설명 된대로 try 또는 catch 내에서 return 이 먼저 실행되고 각각 return 문이 실행됩니다. 그러나 컨트롤을 호출 코드로 되돌리기 전에 finally 블록을 실행합니다. 이제이 block 은 무언가를 반환하기 때문에이 반환 값은 이전 값보다 우선합니다.


(짧은 답변 - 답변의 굵은 기울임 꼴 부분 을 읽으십시오)

자바 8 문서에 따른 실행 흐름. 그것은 당신에게 세부 사항을 제공합니다. 다음을 기반으로 return 문 실행을 유추 할 수 있습니다.

finally 블록이있는 try 문은 try 블록을 먼저 실행하여 실행됩니다.

그런 다음 선택이 있습니다.

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

- finally 블록이 정상적으로 완료되면 try 문이 정상적으로 완료됩니다.

- finally 블록이 이유 S로 인해 갑자기 완료되면 try 문은 이유 S로 인해 갑자기 완료됩니다.

• 값 V의 throw 때문에 try 블록의 실행이 갑자기 완료되면 다음과 같은 선택 사항이 있습니다.

- V의 런타임 유형이 try 문의 catch 카테고리의 catchable exception 클래스와 할당 호환되는 경우 첫 번째 (가장 왼쪽) catch 절이 선택됩니다. V 값은 선택된 catch 절의 매개 변수에 지정되고 해당 catch 절의 Block이 실행됩니다.

그런 다음 선택이 있습니다.

> catch 블록이 정상적으로 완료되면 finally 블록이 실행됩니다. 그런 다음 선택이 있습니다.

»finally 블록이 정상적으로 완료되면 try 문이 정상적으로 완료됩니다.

»어떤 이유로 finally 블록이 갑자기 완료되면 같은 이유로 try 문이 갑자기 완료됩니다.

> 이유 블록 R에 따라 catch 블록이 갑자기 완료되면 finally 블록이 실행됩니다. 그런 다음 선택이 있습니다.

»finally 블록이 정상적으로 완료되면 try 문은 이유 R으로 인해 갑자기 완료됩니다.

» finally 블록이 이유 S로 인해 갑자기 완료되면 try 문은 이유 S (이유 R이 삭제됨)에 따라 갑자기 완료됩니다.

- V의 런타임 유형이 try 문의 catch 카테고리의 catchable exception 클래스와 할당 호환되지 않으면 finally 블록이 실행됩니다.

그런 다음 선택이 있습니다.

> finally 블록이 정상적으로 완료되면 try 문은 값 V가 throw되기 때문에 갑자기 완료됩니다.

> finally 블록이 이유 S로 인해 갑자기 완료되면 try 문은 이유 S로 인해 갑자기 완료되며 값 V의 발생은 무시되고 잊어 버립니다.

• try 블록의 실행이 다른 이유로 R에서 갑자기 완료되면 finally 블록이 실행되고 다음과 같은 선택 사항이 있습니다.

- finally 블록이 정상적으로 완료되면 try 문은 이유 R에 따라 갑자기 완료됩니다.

- finally 블록이 이유 S로 인해 갑자기 완료되면 try 문은 이유 S (이유 R이 삭제됨)에 따라 갑자기 완료됩니다.

이 링크에서는 설명이 명확합니다. javaDoc


Java 언어 스펙에 의해 허용 되었기 때문에 컴파일 오류가 발생하지 않습니다. 그러나 finally 블록에 return 문을 포함시키는 것이 일반적으로 좋지 않기 때문에 경고 메시지를 표시합니다.

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

마찬가지로 finally 블록은 대개 예외를 발생 시켜서는 안됩니다. 따라서 finally 블록이 정상적으로 완료되어야한다는 메시지가 표시됩니다. 즉 return 또는 예외가 발생하지 않습니다.


try, catch 및 finally 블록에 return 문이 하나만 있기 때문에 코드가 올바르게 작동합니다. try, catch 또는 finally 블록 중 하나에 도달 할 수없는 return 문이 있음을 나타내는 두 개의 return 문을 작성하려고하면 컴파일 오류가 발생합니다.


브릴리언트 질문 .. 제 지식에 따르면 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
        }
    }
}

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


어떻게 작동하는지 보여주는 코드가 있습니다.

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

    public static String test()
    {
        try {
            System.out.println("try");
            throw new Exception();
        } catch(Exception e) {
            System.out.println("catch");
            return "return"; 
        } finally {  
            System.out.println("finally");
            return "return in finally"; 
        }
    }
}

결과는 다음과 같습니다.

try
catch
finally
return in finally




java compiler-errors return try-catch try-catch-finally