57
void run() {
    ...
    if (done) return cancel();
    ...
}

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.

Travis Webb
  • 14,688
  • 7
  • 55
  • 109

14 Answers14

25

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

heisenberg
  • 9,665
  • 1
  • 30
  • 38
Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
  • Agree with @Johan that this behavior is according to the standard. But I'd say it would be perfectly natural to allow `return cancel()` as a synonym for `cancel(); return`, or even `void result = cancel(); return result`. – MarnixKlooster ReinstateMonica Oct 18 '11 at 18:03
24

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    `java.lang.Void` can be used for this (see my answer below) – michael667 Oct 17 '11 at 19:00
  • 3
    @michael667 but Void is not void. An interface returning void cannot be implemented by a method returning java.lang.Void. java.lang.Void is only useful to handle void in Reflection and Generics. – josefx Oct 18 '11 at 10:40
9

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.

masoud
  • 55,379
  • 16
  • 141
  • 208
7

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.

michael667
  • 3,241
  • 24
  • 32
  • 1
    True. The only place where I use the `Void` type are `Callables` – michael667 Oct 17 '11 at 19:50
  • 1
    +1 for this answer (and others) because this hits the nail on the head: in Java `void` is not a type, it rather indicates the absence of any type. However, there is no reason why `void` couldn't have been used to represent 'the type which contains no values'. (Scala does this, and calls this type `Unit`.) – MarnixKlooster ReinstateMonica Oct 18 '11 at 18:28
  • Special thanks for explaining Void (with capital V) – Gyro Gearloose Nov 08 '19 at 12:28
5

Because you don't return void. void is not a value, so it can't be returned.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
4

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?

Emoire
  • 49
  • 3
  • @psr: Of course you could. But we're not talking about a compiler that does so. And why would you write one that performed that way? – Emoire Nov 04 '11 at 18:32
  • You know, I can't remember what I was thinking when I wrote this. I think I was thinking that it's not a tautology. But I suppose you meant "true by definition in Java", which it is. Which could be described as a tautology. Maybe I was thinking that there seems to be no harm in allowing a return void, which would be the same as just a return, which would allow the same syntax when calling a method that doesn't return a value (as in the OP) as when calling one that does. Which means its only a tautology in the context of Java, which is oddly un-tautologyish. – psr Nov 04 '11 at 18:47
3

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.
Go Dan
  • 15,194
  • 6
  • 41
  • 65
2

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.

Michael Madsen
  • 54,231
  • 8
  • 72
  • 83
1

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.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • 2
    Because of your grammatical capitalization type, your answer is incorrect. You meant to say that `void` is not a real type because `Void` [most certainly is a real type](http://download.oracle.com/javase/6/docs/api/java/lang/Void.html). – Ryan Stewart Oct 17 '11 at 15:42
1

void is not a type. void in the method definition is just a placeholder for returns nothing.

Sahil Muthoo
  • 12,033
  • 2
  • 29
  • 38
1

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.

dlev
  • 48,024
  • 5
  • 125
  • 132
1

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.

kba
  • 19,333
  • 5
  • 62
  • 89
Prince John Wesley
  • 62,492
  • 12
  • 87
  • 94
1

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.

acjay
  • 34,571
  • 6
  • 57
  • 100
0

A proper way to handle this would be:

void run() {
...
if (done) {
    cancel();
    return;
    }
...
}
djhaskin987
  • 9,741
  • 4
  • 50
  • 86