【问题标题】:Why can't I explicitly return void from a method?为什么我不能从方法中显式返回 void?
【发布时间】:2025-12-19 01:45:06
【问题描述】:
void run() {
    ...
    if (done) return cancel();
    ...
}

cancel() 返回void。这不会编译...我可以几乎理解为什么。但是,如果我想从 void 返回一个 void,为什么不呢?相反,我最终会写这样的东西:

if (done) {
    cancel();
    return;
}

我不是在寻找代码风格的建议,我想知道为什么 Java 明确禁止这种类型的 void 返回。感谢您提供任何信息,谢谢。

【问题讨论】:

  • 自然地,void 函数不会为其调用者提供结果值。
  • 我认为“为什么”问题的唯一可能答案是:询问语言设计者。
  • 该方法不会“返回 void”。该方法没有返回类型。
  • (void) 在函数声明中表示该函数没有返回值。

标签: java void return-type


【解决方案1】:

这就像写作:

void v = (void) 1;
return (v);

所以,我认为 void 不是 Java 中的 type。在 C++ 中,return cancel(); 是合法的。作为熟悉 Java 的 C++ 程序员,答案是:Java 语法不支持很多东西。也许是为了简单或易读。

注意:void f() 声明类似于 pascal 中的 procedure f() 声明,并且过程不能返回函数等任何值,因此我们必须在单独的语句中调用它们。

【讨论】:

    【解决方案2】:

    处理此问题的正确方法是:

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

    【讨论】:

      【解决方案3】:

      简答

      return cancel() 语句必须返回有效值,但方法声明void run() 声明run() 不返回值;因此,run() 中的 return cancel() 是一个错误。 return 语句(不带表达式)尝试将控制权转移给调用者,并在方法返回类型为 void 时使用;因此,不是错误。

      长答案

      JLSThe *return* Statement section 声明:

      没有 Expression 的 return 语句尝试将控制权转移给包含它的方法或构造函数的调用者。 [...] 带有 Expression 的 return 语句必须包含在声明为返回值(第 8.4 节)的方法声明中,否则会发生编译时错误。表达式必须表示某个类型 T 的变量或值,否则会发生编译时错误。类型 T 必须可分配(第 5.2 节)到方法的声明结果类型,否则会发生编译时错误。

      JLS Method Return Type section 声明:

      方法的返回类型声明一个方法返回的值的类型,如果它返回一个值,或者声明该方法是无效的。当且仅当以下条件成立时,具有返回类型 R1 的方法声明 d1 可以返回类型替代具有返回类型 R2 的另一个方法 d2:[...] * 如果 R1 为 void,则 R2 为 void。

      JLS Types, Values, and Variables chapter,第一段指出:

      Java 编程语言是一种强类型语言,这意味着每个变量和每个表达式都具有在编译时已知的类型。类型限制变量(第 4.12 节)可以保存的值或表达式可以产生的值,限制这些值支持的操作,并确定操作的含义。

      JLS The Kinds of Types and Values section 声明:

      Java 编程语言中有两种类型:原始类型(第 4.2 节)和引用类型(第 4.3 节)。相应地,有两种数据值可以存储在变量中、作为参数传递、由方法返回和操作:原始值(第 4.2 节)和参考值(第 4.3 节)。

      现在再多引用几句。 JLS Expression Statements section 声明:

      与 C 和 C++ 不同,Java 编程语言只允许将某些形式的表达式用作表达式语句。请注意,Java 编程语言不允许“强制转换为 void”-void 不是类型

      JLS Method Body section 声明:

      如果方法被声明为 void,则其主体不得包含任何具有表达式的返回语句(第 14.17 节)。

      最后,JLS Method Declarations section 声明:

      方法声明要么指定方法返回的值的类型,要么使用关键字 void 表示方法不返回值。

      现在,当我们将它们拼凑在一起时,我们可以得出以下结论:

      • 如果return 语句包含表达式,则表达式的计算结果必须为有效值。
      • 有效的return 表达式值必须是基本类型或引用类型。
      • void 不是有效的值类型。
      • 使用void 返回类型声明的方法不返回任何值。
      • 方法void run() 不返回值。
      • run()return 中,不带表达式,很乐意将控制权转移给调用者。
      • run() 中,return some expression 是错误的,因为some expression 必须是有效值,而run() 不返回值。

      【讨论】:

        【解决方案4】:

        Java grammar 实际上并不关心方法调用的类型,所以这不是问题。它必须是更下游的东西,在类型检查系统中。我认为底线是 if 在 return 关键字之后包含一个语法上可选的语句,然后系统期望传递一个值。 void 当然一个类型,但是没有类型为void 的值。

        但是,当然,这些都不能真正解释您问题的答案。正如您所指出的,没有理由不允许这个成语。但是也没有正当的理由允许它。所以这是一个折腾。人们可以尝试解释他们为什么要这样做,但这可能毫无意义。

        【讨论】:

          【解决方案5】:

          这是一个有趣的问题。由于 java 强制执行返回类型(void 是返回类型),您的第一条语句似乎是有道理的。我认为这只是为了约定。由于void 是一个占位符而不是一个对象,因此可能出于语言一致性或编译器的简单性而决定将其排除在外。

          来自JLS

          没有表达式的 return 语句必须包含在声明的方法的主体中,使用关键字 void,不返回任何值(第 8.4 节),或在构造函数的主体中(第 8.8 节)。

          进一步

          确切地说,没有表达式的返回语句总是突然完成,原因是没有值的返回

          【讨论】:

          • 同意@Johan,这种行为符合标准。但我想说让return cancel() 成为cancel(); return 甚至void result = cancel(); return result 的同义词是非常自然的。
          【解决方案6】:

          来自 JLS:

          没有表达式的返回语句必须包含在 使用关键字 void 声明的方法,不返回任何 值,或者在构造函数的主体中

          ...

          带有表达式的返回语句必须包含在方法中 声明为返回值或编译时的声明 发生错误。表达式必须表示某个变量或值 类型 T,或发生编译时错误。类型 T 必须是可分配的 到方法的声明结果类型,或编译时错误 发生。

          【讨论】:

            【解决方案7】:

            这是一个重言式。意思是,void 定义该方法没有返回值。因此,当 void 根本没有回报时,你怎么能“返回 void”?

            【讨论】:

            • @psr:当然可以。但我们不是在谈论这样做的编译器。你为什么要写一个那样的表现?
            • 你知道,我不记得我写这篇文章的时候在想什么。我想我在想这不是同义反复。但是我想您的意思是“在Java中定义为真”,就是这样。这可以被描述为重言式。也许我在想允许返回 void 似乎没有什么害处,这与返回相同,在调用不返回值的方法时允许使用相同的语法(如在 OP 中)就像打电话一样。这意味着它只是 Java 上下文中的重言式,奇怪的是没有重言式。
            【解决方案8】:

            有趣的想法。主要问题是语言规范,它将返回语句定义为由return <expression> 组成。 void 方法不是表达式,因此不允许构造。

            您发现您可以通过执行 void 方法然后返回来复制功能,因此没有真正的理由允许它。

            【讨论】:

              【解决方案9】:

              void 不是类型。但是,如果您使用 Void 类型而不是 void 关键字,您的代码将可以工作,但是:您必须手动在方法的所有退出点中使用 return null

              【讨论】:

              • 是的。我唯一使用Void 类型的地方是Callables
              • +1 为这个答案(和其他人),因为这击中了头上的钉子:在 Java 中 void 不是一种类型,而是表示没有任何类型。但是,没有理由不能使用void 来表示“不包含值的类型”。 (Scala 会这样做,并将这种类型称为 Unit。)
              • 特别感谢解释Void(大写V)
              【解决方案10】:

              带有表达式的 return 语句返回该表达式的值。 cancel() 的类型是一个 void 表达式 - 它没有 值。

              逻辑上你想执行cancel(),然后返回——这就是你要说的。这两个操作(调用cancel() 然后返回)在逻辑上是不同的。

              现在 Java 可以有一种 "unit" type 而不是 void - 但这会影响的不仅仅是返回值。

              【讨论】:

              • java.lang.Void 可用于此(请参阅下面的答案)
              • @michael667 但 Void 不是无效的。返回 void 的接口不能由返回 java.lang.Void 的方法实现。 java.lang.Void 仅对处理反射和泛型中的 void 有用。
              【解决方案11】:

              return x 明确表示“返回值 x”,无论该类型是什么(当然,该类型仍然必须匹配该语句所在的任何函数的返回类型)。

              void 严格来说是一种类型的 absence,并且通过扩展,没有值 - 所以返回一个没有意义,就像它没有感觉(并且不允许)声明 void 变量。

              【讨论】:

                【解决方案12】:

                void 不是类型。方法定义中的void 只是一个占位符,不返回任何内容。

                【讨论】:

                  【解决方案13】:

                  Void 不是真正的类型。 Void 只是一个占位符,使方法定义的语法更加一致。这不是 java 的创新;这是从 C 继承的。

                  这就是编译器不允许你写return cancel()的原因,即使方法cancel()void

                  【讨论】:

                  • 由于您的语法大写类型,您的答案不正确。你的意思是说void 不是真正的类型,因为Void most certainly is a real type
                  【解决方案14】:

                  因为你没有返回voidvoid 不是值,所以无法返回。

                  【讨论】: