Why can't I explicitly return void from a method?
void run() {
...
if (done) return canc开发者_Python百科el();
...
}
where cancel()
return void
. This won't compile... and I can almost understand why. But if I want to return a void from a void, why not? Instead, I end up writing something like this:
if (done) {
cancel();
return;
}
I'm not looking for code style suggestions, I want to know why Java expressly prohibits this type of void return. Any info is appreciated, thanks.
It's an interesting question. Since java enforces a return type (void
is a return type) your first statement seems to make sense. I would take this only for convention. Since void
is a placeholder and not an object, it was probably decided to leave it out for language coherency or compiler simplicity.
From JLS
A return statement with no Expression must be contained in the body of a method that is declared, using the keyword void, not to return any value (§8.4), or in the body of a constructor (§8.8).
further
To be precise, a return statement with no Expression always completes abruptly, the reason being a return with no value
A return statement with an expression returns the value of that expression. The type of cancel()
is a void expression - it doesn't have a value.
Logically you want to execute cancel()
, and then return - so that's what you have to say. The two actions (calling cancel()
and then returning) are logically distinct.
Now Java could have a sort of "unit" type instead of void
- but that would affect rather more than just return values.
It's like writing:
void v = (void) 1;
return (v);
So, I think void
is not a type
in Java. In C++, return cancel();
is legal. As a C++ programmer who is familiar with Java the answer is: Many things are not supported in Java syntax. Maybe for simplicity or readibility.
Note: A void f()
declaration is similar to a procedure f()
declaration in pascal and a procedure could not return any value such as functions, so we must call them in a separated statement.
void
is not a type. If you use the Void
type instead of the void
keyword, however, your code will work, but: You'll manually have to return null
in all exit points from your method.
Because you don't return void
. void
is not a value, so it can't be returned.
It's a tautology. Meaning, void defines that the method has no return value. Therefore, how can you "return void" when void is no return at all?
Short Answer
The return cancel()
statement must return a valid value, but the method declaration void run()
declares that run()
does not return a value; hence, return cancel()
in run()
is an error. The return
statement (without an expression) attempts to transfer control to the caller and is used when the method return type is void
; hence, not an error.
Long Answer
The JLS The *return* Statement
section states:
A return statement with no Expression attempts to transfer control to the invoker of the method or constructor that contains it. [...] A return statement with an Expression must be contained in a method declaration that is declared to return a value (§8.4) or a compile-time error occurs. The Expression must denote a variable or value of some type T, or a compile-time error occurs. The type T must be assignable (§5.2) to the declared result type of the method, or a compile-time error occurs.
The JLS Method Return Type
section states:
The return type of a method declares the type of value a method returns, if it returns a value, or states that the method is void. A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2, if and only if the following conditions hold: [...] * If R1 is void then R2 is void.
The JLS Types, Values, and Variables
chapter, first paragraph states:
The Java programming language is a strongly typed language, which means that every variable and every expression has a type that is known at compile time. Types limit the values that a variable (§4.12) can hold or that an expression can produce, limit the operations supported on those values, and determine the meaning of the operations.
The JLS The Kinds of Types and Values
section states:
There are two kinds of types in the Java programming language: primitive types (§4.2) and reference types (§4.3). There are, correspondingly, two kinds of data values that can be stored in variables, passed as arguments, returned by methods, and operated on: primitive values (§4.2) and reference values (§4.3).
Just a few more quotes now. The JLS Expression Statements
section states:
Unlike C and C++, the Java programming language allows only certain forms of expressions to be used as expression statements. Note that the Java programming language does not allow a "cast to void"-void is not a type
The JLS Method Body
section states:
If a method is declared void, then its body must not contain any return statement (§14.17) that has an Expression.
And, finally, the JLS Method Declarations
section states:
A method declaration either specifies the type of value that the method returns or uses the keyword void to indicate that the method does not return a value.
Now, when we piece it all together, we can deduce the following:
- If a
return
statement contains an expression, the expression must evaluate to a valid value. - A valid
return
expression value must be a primitive type or a reference type. void
is not a valid value type.- A method declared with a
void
return type, returns no value. - Method
void run()
does not return a value. - In
run()
,return
, without an expression, will happily transfer control to the caller. - In
run()
,return some expression
is an error becausesome expression
must be a valid value andrun()
does not return a value.
return x
explicitly means "return the value x", regardless of what that type is (the type, of course, still has to match the return type of whatever function that statement is placed in).
void
is, strictly speaking, the absence of a type, and by extension, the absence of a value - so it does not make sense to return one, just like it does not make sense (and is not allowed) to declare a void
variable.
Void is not a real type. Void is just a place holder to make syntax of methods definition more consistent. This is not the java innovation; this is inherited from C.
This is the reason that compiler does not allow you to write return cancel()
even if method cancel()
is void
.
void
is not a type. void
in the method definition is just a placeholder for returns nothing.
Interesting idea. The main issue is the language spec, which defines a return statement as being composed of return <expression>
. A void method is not an expression, so the construct isn't permitted.
You've found that you can replicate the functionality by executing the void method and then returning, so there's no real reason to allow it.
From the JLS:
A return statement with no Expression must be contained in the body of a method that is declared, using the keyword void, not to return any value, or in the body of a constructor
...
A return statement with an Expression must be contained in a method declaration that is declared to return a value or a compile-time error occurs. The Expression must denote a variable or value of some type T, or a compile-time error occurs. The type T must be assignable to the declared result type of the method, or a compile-time error occurs.
The Java grammar actually doesn't care about the type of a method call, so that's not the issue. It has to be something farther down the chain, in the type-checking system. I think the bottom line is that if a grammatically optional statement is included after the return keyword, then the system expects a value to pass on. void
certainly is a type, but there are no values with type void
.
But, of course, none of this really explains the answer to your question. As you pointed out, there's no reason why this idiom should not be allowed. But there's also no valid reason to allow it. So it's a toss up. One could try to rationalize why they did what they did, but that would probably be pointless.
A proper way to handle this would be:
void run() {
...
if (done) {
cancel();
return;
}
...
}
精彩评论