开发者

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 because some expression must be a valid value and run() 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;
    }
...
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜