为什么我不能从方法中明确地返回void?
void run() { ... if (done) return cancel(); ... }
在那里cancel()
返回void
。 这不会编译…我几乎可以理解为什么。 但是如果我想从虚空中回归一个虚空,为什么不呢? 相反,我最终写了这样的东西:
if (done) { cancel(); return; }
我不是在寻找代码风格的build议,我想知道为什么Java明确禁止这种types的无效返回。 任何信息表示赞赏,谢谢。
带有expression式的返回语句返回该expression式的值。 cancel()
的types是一个voidexpression式 – 它没有一个值。
逻辑上你想执行cancel()
,然后返回 – 这就是你必须说的。 这两个动作(调用cancel()
然后返回)在逻辑上是不同的。
现在Java 可以有一种“单位”types而不是void
– 但是这不仅仅会影响返回值。
这是一个有趣的问题。 由于Java强制返回types( void
是一个返回types),所以你的第一个语句似乎是有道理的。 我会把这只作为惯例。 由于void
是一个占位符,而不是一个对象,因此可能决定将它留给语言一致性或编译器简单性。
从JLS
没有expression式的return语句必须包含在声明方法的主体中,使用关键字void,不返回任何值(§8.4),或者在构造函数的主体中(§8.8)。
进一步
确切地说,没有expression式的return语句总是突然完成,原因是没有值的返回
这就像写作:
void v=(void)1; return (v);
所以,我认为void
不是Java中的一种type
。
在C ++中, return cancel();
是合法的。
作为熟悉Java的C ++程序员,答案是:Java语法中不支持许多事情。 也许为了简单或可读性。
注意: void f()
声明与pascal中的procedure f()
声明类似, procedure f()
无法返回任何值,例如函数,所以我们必须以分隔的语句调用它们。
void
不是一个types。 但是,如果使用Void
types而不是void
关键字,那么代码将起作用,但是:手动必须在方法的所有出口点都return null
。
因为你不回报 void
。 void
不是一个值,所以它不能被返回。
这是一个重言式。 意思是,void定义了方法没有返回值。 因此,如果虚空无济于事,又怎能“虚空”呢?
简答
return cancel()
语句必须返回一个有效的值,但是方法声明void run()
声明run()
不返回一个值。 因此,在run()
return cancel()
run()
是一个错误。 return
语句(没有expression式)尝试将控制权转移给调用者,并在方法返回types为void
; 因此,不是一个错误。
长答案
JLS The *return* Statement
部分说明:
没有expression式的return语句尝试将控制权转移给包含它的方法或构造函数的调用者。 […]带有Expression的返回语句必须包含在声明为返回值(第8.4节)或发生编译时错误的方法声明中。 expression式必须表示某个typesT的variables或值,否则会发生编译时错误。 typesT必须是可分配的(第5.2节)到方法的声明结果types,否则会发生编译时错误。
JLS Method Return Type
部分指出:
方法的返回types声明方法返回的值的types,如果它返回一个值,或者声明该方法是无效的。 返回types为R1的方法声明d1对于返回types为R2的另一个方法d2是return-type-substitutable当且仅当以下条件成立时:[…] *如果R1为无效,则R2为无效。
JLS Types, Values, and Variables
章节 ,第一段指出:
Java编程语言是一种强types语言,这意味着每个variables和每个expression式都有一个在编译时已知的types。 types限制variables(§4.12)可以容纳的值或expression式可以产生的值,限制这些值所支持的操作,并确定操作的含义。
JLS The Kinds of Types and Values
部分指出:
Java编程语言中有两种types:基本types(§4.2)和引用types(§4.3)。 相应地,有两种数据值可以存储在variables中,作为parameter passing,通过方法返回,并对原始值(§4.2)和参考值(§4.3)进行操作。
现在只是更多的报价。 JLS Expression Statements
部分指出:
与C和C ++不同,Java编程语言只允许将某些forms的expression式用作expression式语句。 请注意,Java编程语言不允许“转换为空”-void不是一种types
JLS Method Body
部分指出:
如果一个方法被声明为void,那么它的主体不能包含任何具有expression式的return语句(§14.17)。
最后,JLS Method Declarations
部分指出:
方法声明要么指定方法返回的值的types,要么使用关键字void来指示方法不返回值。
现在,当我们把所有的东西拼在一起的时候,我们可以推导出以下结论:
- 如果
return
语句包含expression式,则expression式必须计算为有效值。 - 有效的
return
expression式值必须是基元types或引用types。 -
void
不是有效的值types。 - 用
void
返回types声明的方法不返回任何值。 - 方法
void run()
不会返回一个值。 - 在
run()
,return
,没有expression式,将愉快地将控制权转移给调用者。 - 在
run()
,return some expression
是一个错误,因为some expression
必须是一个有效的值,run()
不会返回一个值。
显式return x
意思是“返回值x”,不pipetypes是什么(当然,types仍然必须匹配任何函数的返回types)。
严格地说, void
是缺less一个types的,也就是说,缺less一个值 – 所以返回一个值是没有意义的,就像没有意义(也不允许)声明一个void
variables。
虚空不是一个真正的types。 Void只是使方法定义的语法更加一致的占位符。 这不是Java的创新; 这是从C.inheritance
这是编译器不允许你写return cancel()
的原因,即使方法cancel()
是void
。
void
不是一个types。 方法定义中的void
只是一个返回void
的占位符。
有趣的想法。 主要的问题是语言规范,它将return语句定义为由return <expression>
。 void方法不是expression式,所以构造是不允许的。
你发现你可以通过执行void方法来复制function,然后返回,所以没有真正的理由允许它。
从JLS:
没有expression式的return语句必须包含在声明方法的主体中,使用关键字void,不返回任何值,或者在构造函数的主体中
…
带有Expression的返回语句必须包含在声明为返回值或发生编译时错误的方法声明中。 expression式必须表示某个typesT的variables或值,否则会发生编译时错误。 typesT必须可分配给方法的声明结果types,否则会发生编译时错误。
Java语法实际上并不关心方法调用的types,所以这不是问题。 在types检查系统中,它必须是更下游的东西。 我认为底线是, 如果在return关键字之后包含语法上可选的语句,那么系统需要传递一个值。 void
当然是一个types,但是void
types没有值。
但是,当然,这些都不能解释你的问题的答案。 正如你所指出的,这个成语不应该被允许。 但是也没有合理的理由允许。 所以这是一个折腾。 人们可以尝试合理化为什么他们做了他们所做的事情,但这可能是毫无意义的。
处理这个问题的正确方法是:
void run() { ... if (done) { cancel(); return; } ... }