무효가 아닌 메소드 컴파일에서 누락 된 리턴 문
void 가 아닌 메소드 에 return 문 이 누락 되어 코드가 여전히 컴파일 되는 상황이 발생했습니다 . while 루프 뒤의 명령문은 도달 할 수 없으며 (데드 코드) 결코 실행될 수 없다는 것을 알고 있습니다. 그러나 컴파일러가 왜 무언가를 반환하는 것에 대해 경고하지 않습니까? 아니면 왜 언어를 사용하여 무한 루프를 가지고 있고 아무것도 반환하지 않는 비 공백 메소드를 가질 수 있습니까?
public int doNotReturnAnything() {
while(true) {
//do something
}
//no return statement
}
while 루프에 break 문 (조건문 하나)을 추가하면 컴파일러는 악명 높은 오류 ( Method does not return a value
Eclipse 및 Not all code paths return a value
Visual Studio) 에 대해 불평합니다 .
public int doNotReturnAnything() {
while(true) {
if(mustReturn) break;
//do something
}
//no return statement
}
이것은 Java와 C # 모두에 해당됩니다.
왜 언어를 사용하면 무한 루프를 가지고 있고 아무것도 반환하지 않는 비 공백 메소드를 가질 수 있습니까?
무효가 아닌 메소드의 규칙 은 리턴하는 모든 코드 경로가 값을 리턴해야 하며 해당 규칙이 프로그램에서 충족되는 것입니다. 리턴하는 0 개의 코드 경로 중 0은 값을 리턴합니다. 이 규칙은 "모든 비 공백 메소드는 리턴하는 코드 경로를 가져야합니다"는 아닙니다.
이를 통해 다음과 같은 스텁 메소드를 작성할 수 있습니다.
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
그것은 무효가 아닌 방법입니다. 그것은 갖는 인터페이스를 충족하기 위해 비 공간있어서한다. 그러나이 구현을 아무것도 반환하지 않기 때문에 불법으로 만드는 것은 어리석은 것처럼 보입니다.
당신의 방법은 때문에의 도달 끝 지점을 가지고 goto
(A는 기억 while(true)
쓰기 단지 더 즐거운 방법입니다 goto
대신의) throw
(의 또 다른 형태 인 goto
) 관련이 없습니다.
컴파일러는 왜 무언가를 반환하는 것에 대해 경고하지 않습니까?
컴파일러는 코드가 잘못되었다는 좋은 증거가 없기 때문입니다. 누군가가 글을 썼는데 while(true)
, 그 일을 한 사람이 자신이하는 일을 알고있을 것 같습니다.
C #의 도달 가능성 분석에 대한 자세한 내용은 어디서 볼 수 있습니까?
주제에 대한 내 기사를 참조하십시오.
그리고 C # 사양을 읽는 것도 고려할 수 있습니다.
Java 컴파일러는 도달 할 수없는 코드 ( while
루프 후 코드)를 찾을 수있을 정도로 똑똑합니다.
그 이후로 도달 할 수없는 , 아무 소용이없는 추가에서 return
이 문 (후 while
종료)
조건부와 동일 if
public int get() {
if(someBoolean) {
return 10;
}
else {
return 5;
}
// there is no need of say, return 11 here;
}
부울 조건 someBoolean
은 true
또는 로만 평가할 수 있으므로 해당 코드에 도달 할 수 없고 Java가 이에 대해 불평하지 않기 때문에 명시 적으로 after false
를 제공 할 필요 가 없습니다.return
if-else
컴파일러는 while
루프가 실행을 멈추지 않으므로 메소드가 완료 return
되지 않으므로 명령문이 필요하지 않다는 것을 알고 있습니다.
루프가 상수로 실행되고 있다고 가정하면 컴파일러는 무한 루프라는 것을 알고 있습니다.
변수를 사용하면 컴파일러가 규칙을 시행합니다.
이것은 컴파일되지 않습니다 :
// Define other methods and classes here
public int doNotReturnAnything() {
var x = true;
while(x == true) {
//do something
}
//no return statement - won't compile
}
The Java specification defines a concept called Unreachable statements
. You are not allowed to have an unreachable statement in your code (it's a compile time error). You are not even allowed to have a return statement after the while(true); statement in Java. A while(true);
statement makes the following statements unreachable by definition, therefore you don't need a return
statement.
Note that while Halting problem is undecidable in generic case, the definition of Unreachable Statement is more strict than just halting. It's deciding very specific cases where a program definitely does not halt. The compiler is theoretically not able to detect all infinite loops and unreachable statements but it has to detect specific cases defined in the specification (for example, the while(true)
case)
The compiler is smart enough to find out that your while
loop is infinite.
So the compiler cannot think for you. It cannot guess why you wrote that code. Same stands for the return values of methods. Java won't complain if you don't do anything with method's return values.
So, to answer your question:
The compiler analyzes your code and after finding out that no execution path leads to falling off the end of the function it finishes with OK.
There may be legitimate reasons for an infinite loop. For example a lot of apps use an infinite main loop. Another example is a web server which may indefinitely wait for requests.
In type theory, there is something called the bottom type which is a subclass of every other type (!) and is used to indicate non-termination among other things. (Exceptions can count as a type of non-termination--you don't terminate via the normal path.)
So from a theoretical perspective, these statements that are non-terminating can be considered to return something of Bottom type, which is a subtype of int, so you do (kind of) get your return value after all from a type perspective. And it's perfectly okay that it doesn't make any sense that one type can be a subclass of everything else including int because you never actually return one.
In any case, via explicit type theory or not, compilers (compiler writers) recognize that asking for a return value after a non-terminating statement is silly: there is no possible case in which you could need that value. (It can be nice to have your compiler warn you when it knows something won't terminate but it looks like you want it to return something. But that's better left for style-checkers a la lint, since maybe you need the type signature that way for some other reason (e.g. subclassing) but you really want non-termination.)
There is no situation in which the function can reach its end without returning an appropriate value. Therefore, there is nothing for the compiler to complain about.
Visual studio has the smart engine to detect if you have typed a return type then it should have a return statement with in the function/method.
As in PHP Your return type is true if you have not returned anything. compiler get 1 if nothing has returned.
As of this
public int doNotReturnAnything() {
while(true) {
//do something
}
//no return statement
}
Compiler know that while statement itself has a infinte nature so not to consider it. and php compiler will automatically get true if you write a condition in expression of while.
But not in the case of VS it will return you a error in the stack .
Your while loop will run forever and hence won't come outside while; it will continue to execute. Hence, the outside part of while{} is unreachable and there is not point in writing return or not. The compiler is intelligent enough to figure out what part is reachable and what part isn't.
Example:
public int xyz(){
boolean x=true;
while(x==true){
// do something
}
// no return statement
}
The above code won't compile, because there can be a case that the value of variable x is modified inside the body of while loop. So this makes the outside part of while loop reachable! And hence compiler will throw an error 'no return statement found'.
The compiler is not intelligent enough (or rather lazy ;) ) to figure out that whether the value of x will be modified or not. Hope this clears everything.
"Why doesn't the compiler even warn about returning something? Or why would a language allow us to have a non-void method having an infinite loop and not returning anything?".
This code is valid in all other languages too (probably except Haskell!). Because the first assumption is we are "intentionally" writing some code.
And there are situations that this code can be totally valid like if you are going to use it as a thread; or if it was returning a Task<int>
, you could do some error checking based on the returned int value - which should not be returned.
I may be wrong but some debuggers allow modification of variables. Here while x is not modified by code and it will be optimized out by JIT one might modify x to false and method should return something (if such thing is allowed by C# debugger).
The specifics of the Java case for this (which are probably very similar to the C# case) are to do with how the Java compiler determines if a method is able to return.
Specifically, the rules are that a method with a return type must not be able to complete normally and must instead always complete abruptly (abruptly here indicating via a return statement or an exception) per JLS 8.4.7.
If a method is declared to have a return type, then a compile-time error occurs if the body of the method can complete normally. In other words, a method with a return type must return only by using a return statement that provides a value return; it is not allowed to "drop off the end of its body".
The compiler looks to see whether normal termination is possible based on the rules defined in JLS 14.21 Unreachable Statements as it also defines the rules for normal completion.
Notably, the rules for unreachable statements make a special case just for loops that have a defined true
constant expression:
A while statement can complete normally iff at least one of the following is true:
The while statement is reachable and the condition expression is not a constant expression (§15.28) with value true.
There is a reachable break statement that exits the while statement.
So if the while
statement can complete normally, then a return statement below it is necessary since the code is deemed reachable, and any while
loop without a reachable break statement or constant true
expression is considered able to complete normally.
These rules mean that your while
statement with a constant true expression and without a break
is never considered to complete normally, and so any code below it is never considered to be reachable. The end of the method is below the loop, and since everything below the loop is unreachable, so is the end of the method, and thus the method cannot possibly complete normally (which is what the complier looks for).
if
statements, on the other hand, do not have the special exemption regarding constant expressions that are afforded to loops.
Compare:
// I have a compiler error!
public boolean testReturn()
{
final boolean condition = true;
if (condition) return true;
}
With:
// I compile just fine!
public boolean testReturn()
{
final boolean condition = true;
while (condition)
{
return true;
}
}
The reason for the distinction is quite interesting, and is due to the desire to allow for conditional compilation flags that do not cause compiler errors (from the JLS):
One might expect the if statement to be handled in the following manner:
An if-then statement can complete normally iff at least one of the following is true:
The if-then statement is reachable and the condition expression is not a constant expression whose value is true.
The then-statement can complete normally.
The then-statement is reachable iff the if-then statement is reachable and the condition expression is not a constant expression whose value is false.
An if-then-else statement can complete normally iff the then-statement can complete normally or the else-statement can complete normally.
The then-statement is reachable iff the if-then-else statement is reachable and the condition expression is not a constant expression whose value is false.
The else-statement is reachable iff the if-then-else statement is reachable and the condition expression is not a constant expression whose value is true.
This approach would be consistent with the treatment of other control structures. However, in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules differ.
As an example, the following statement results in a compile-time error:
while (false) { x=3; }
because the statementx=3;
is not reachable; but the superficially similar case:
if (false) { x=3; }
does not result in a compile-time error. An optimizing compiler may realize that the statementx=3;
will never be executed and may choose to omit the code for that statement from the generated class file, but the statementx=3;
is not regarded as "unreachable" in the technical sense specified here.The rationale for this differing treatment is to allow programmers to define "flag variables" such as:
static final boolean DEBUG = false;
and then write code such as:
if (DEBUG) { x=3; }
The idea is that it should be possible to change the value of DEBUG from false to true or from true to false and then compile the code correctly with no other changes to the program text.
Why does the conditional break statement result in a compiler error?
As quoted in the loop reachability rules, a while loop can also complete normally if it contains a reachable break statement. Since the rules for the reachability of an if
statement's then clause do not take the condition of the if
into consideration at all, such a conditional if
statement's then clause is always considered reachable.
If the break
is reachable, then the code after the loop is once again also considered reachable. Since there is no reachable code that results in abrupt termination after the loop, the method is then considered able to complete normally, and so the compiler flags it as an error.
참고URL : https://stackoverflow.com/questions/16789832/missing-return-statement-in-a-non-void-method-compiles
'IT story' 카테고리의 다른 글
최대 절전 모드-cascade =”all-delete-orphan”을 가진 컬렉션이 더 이상 소유 엔티티 인스턴스에 의해 참조되지 않았습니다 (0) | 2020.05.14 |
---|---|
IntelliJ 별표 (패키지) 가져 오기를 비활성화 하시겠습니까? (0) | 2020.05.14 |
Java 8 스트림 및 어레이 작업 (0) | 2020.05.14 |
node.js에 JS 대신 CoffeeScript를 사용할 수 있습니까? (0) | 2020.05.14 |
XSLT에서 새로운 라인 생성 (0) | 2020.05.14 |