리턴 유형이없는 Java 메소드는 리턴 명령문없이 컴파일
질문 1:
왜 다음 코드가 return 문없이 컴파일됩니까?
public int a() {
while(true);
}
통지 : 잠시 후에 return을 추가하면을 얻습니다 Unreachable Code Error
.
질문 2 :
반면에 다음 코드는 왜 컴파일됩니까?
public int a() {
while(0 == 0);
}
비록 다음과 같지 않지만.
public int a(int b) {
while(b == b);
}
질문 1:
왜 다음 코드가 return 문없이 컴파일됩니까?
public int a() { while(true); }
이것은 JLS§8.4.7에 의해 다루어진다 :
메소드가 리턴 유형 (§8.4.5)을 갖도록 선언 된 경우 메소드 본문이 정상적으로 완료 될 수 있으면 (§14.1) 컴파일 타임 오류가 발생합니다.
즉, 리턴 유형이있는 메소드는 값 리턴을 제공하는 리턴 명령문을 사용해야 만 리턴해야합니다. 이 방법은 "본체의 끝을 제거"할 수 없습니다. 메소드 본문의 리턴 문에 대한 정확한 규칙은 §14.17을 참조하십시오.
메소드는 리턴 유형을 가질 수 있지만 리턴 명령문을 포함하지 않을 수 있습니다. 다음은 하나의 예입니다.
class DizzyDean { int pitch() { throw new RuntimeException("90 mph?!"); } }
컴파일러는 루프가 종료되지 않는다는 것을 알고 있기 때문에 ( true
물론 항상 참임), 함수가 "정상적으로 복귀 할 수 없음"(본체의 끝을 떨어 뜨림) 할 수 없다는 것을 알고 있으므로 아무 것도 없어도 return
됩니다.
질문 2 :
반면에 다음 코드는 왜 컴파일됩니까?
public int a() { while(0 == 0); }
비록 다음과 같지 않지만.
public int a(int b) { while(b == b); }
이 0 == 0
경우 컴파일러는 루프가 종료되지 않는다는 것을 알고 0 == 0
있습니다 ( 항상 참임). 그러나 그것은 하지 않습니다 에 대한 알고 b == b
.
왜 안돼?
컴파일러는 상수 표현식 (§15.28)을 이해 합니다. 인용 §15.2-표현의 형태 (이상하게도이 문장이 §15.28에 없기 때문에) :
일부 표현식에는 컴파일 타임에 결정할 수있는 값이 있습니다. 이들은 일정한 표현입니다 (§15.28).
귀하의 b == b
예에서 관련된 변수가 있기 때문에 상수 표현식이 아니며 컴파일 타임에 결정되도록 지정되지 않았습니다. 우리는 (경우에 있지만 항상이 경우에는 사실이 될 것 것을 볼 수 b
있었던이 double
QBrute과 같이, 지적 , 우리가 쉽게 현혹 될 수 Double.NaN
있는, 아니 ==
그 자체 )하지만, JLS 상수 표현식이 컴파일시에 결정됩니다 만 지정 컴파일러가 상수가 아닌 표현식을 평가할 수 없습니다. bayou.io 는 다음과 같은 이유에 대한 좋은 점 을 제시했습니다. b == b
명백하다 (er, non-NaN
값), 그러나 어떻 a + b == b + a
습니까? 아니면 (a + b) * 2 == a * 2 + b * 2
? 상수로 선을 그리는 것이 좋습니다.
따라서 표현식을 "결정"하지 않기 때문에 컴파일러는 루프가 종료되지 않는다는 것을 알지 못하므로 메소드가 정상적으로 리턴 될 수 있다고 생각합니다 return
. 따라서의 부족에 대해 불평합니다 return
.
메소드 리턴 유형을 지정된 유형 의 값을 리턴하는 약속 이 아니라 지정된 유형 이 아닌 값을 리턴 하지 않는 약속으로 생각하면 흥미로울 수 있습니다 . 따라서 아무 것도 반환하지 않으면 약속을 어 기지 않으므로 다음 중 하나가 합법입니다.
영원히 반복 :
X foo() { for (;;); }
영원히 되풀이 :
X foo() { return foo(); }
예외를 던지기 :
X foo() { throw new Error(); }
(재밌는 재귀를 발견했습니다. 컴파일러는 메소드가 유형의 값 X
(무엇이든)을 리턴 할 것이라고 생각 하지만 생성 또는 생성 방법에 대한 아이디어가있는 코드가 없기 때문에 사실이 아닙니다. 를 조달하십시오 X
.)
바이트 코드를 보면 반환되는 내용이 정의와 일치하지 않으면 컴파일 오류가 발생합니다.
예:
for(;;)
바이트 코드를 보여줍니다 :
L0
LINENUMBER 6 L0
FRAME SAME
GOTO L0
리턴 바이트 코드가 없다는 점에 유의하십시오.
이것은 결코 리턴을 누르지 않으므로 잘못된 유형을 리턴하지 않습니다.
비교를 위해 다음과 같은 방법이 있습니다.
public String getBar() {
return bar;
}
다음 바이트 코드를 반환합니다.
public java.lang.String getBar();
Code:
0: aload_0
1: getfield #2; //Field bar:Ljava/lang/String;
4: areturn
"참조"를 의미하는 "return"에 유의하십시오.
이제 다음을 수행하면
public String getBar() {
return 1;
}
다음 바이트 코드를 반환합니다.
public String getBar();
Code:
0: iconst_1
1: ireturn
이제 정의의 유형이 ireturn의 리턴 유형과 일치하지 않음을 알 수 있습니다. 이는 return int를 의미합니다.
따라서 실제로 결과는 메소드에 리턴 경로가 있으면 해당 경로가 리턴 유형과 일치해야한다는 것입니다. 그러나 바이트 경로에는 반환 경로가 전혀 생성되지 않아 규칙을 어 기지 않는 인스턴스가 있습니다.
'IT story' 카테고리의 다른 글
C ++ 11에 도입 된 주요 변경 사항은 무엇입니까? (0) | 2020.04.18 |
---|---|
"범위 기반 for 루프"에서 작동하도록 사용자 정의 유형을 만드는 방법은 무엇입니까? (0) | 2020.04.18 |
GDB에서 '메모리 액세스'에 중단 점을 설정할 수 있습니까? (0) | 2020.04.18 |
CPython에서 GIL (Global Interpreter Lock)이란 무엇입니까? (0) | 2020.04.18 |
IIS7 gzip 사용 (0) | 2020.04.18 |