返回变量和返回计算值之间的区别

时间:2016-11-07 17:38:02

标签: java return-value

在Java中创建一个返回值的方法时,我总是可以返回计算值或保存所述值的变量。例如:

public int sum(int a, int b) 
{
    return a+b;
} 

public int sum(int a, int b) 
{
    int res = a + b;
    return res;
} 

我的问题是,除了可读性之外,第一种方法和第二种方法有什么区别?

return语句如何工作?它是否在"返回"之前创建变量?它到了调用方法的程度?

哪个版本最好,在节省内存方面? 我只是给出了一个简单的例子,但问题代表了各种返回方法。

4 个答案:

答案 0 :(得分:4)

  

我总是可以返回一个包含所述计算的计算或变量。

那是错的。您返回的是值,而不是计算值。

除了你的措辞,没有区别。在这两种情况下,Java编译器可能会生成相同的字节码,因为它会考虑将res作为中间占位符进行优化。

要了解Java return语句的工作原理,您必须了解Java Bytecode ABI的工作原理。您会注意到JVM是一个堆栈计算机 - 因此,如果我没有弄错,无论您以前做过什么,返回值都会在函数调用结束时位于堆栈顶部。 / p>

请注意,尽管进行了进一步的编译时优化,但Javac可能没有“内联”#34;方法调用,如果它没有副作用。但是,一旦我们谈论"聪明"优化,询问特定语言概念如何工作可能是一个没有实际意义的点,因为它们可能会被优化掉。

答案 1 :(得分:0)

第一个示例更具可读性,维护错误的可能性更小,因为您没有在return语句之前可能会意外破坏的变量。

还有一些数据类型问题可以在方法的数据类型,您的' res'的数据类型之间引入。变量和正在计算的表达式的数据类型。这不是你的例子中的问题,但是由于其他原因引入的中间变量比你已经证明的更具风险,而不仅仅是将表达式放在return语句中。

答案 2 :(得分:0)

JVM是一个堆栈计算机,返回值始终在堆栈上。如果您编译这两个函数,您将看到生成的代码确实不同:

public int withVar(int a, int b);
  Code:
     0: iload_1 (int a)
     1: iload_2 (int b)
     2: iadd
     3: istore_3 (int res)
     4: iload_3 (int res)
     5: ireturn

public int withoutVar(int a, int b);
  Code:
     0: iload_1 (int a)
     1: iload_2 (int b)
     2: iadd
     3: ireturn

可以看出,较长的版本实际上填充了第三个局部变量槽(istore_3)。但是,由于永远不会使用该值,任何理智的JIT都会快速优化多余的操作。

所以对于速度:只是不要打扰。关于可读性?这取决于......我找到了像

这样的成语
public void func() {
    final int res;
    // do something
    return res;
}

有时非常方便。

  • 编译器会检查res的单个赋值,因此只需一次返回,就可以保证代码中没有直通路径的编译时保证。
  • return res上设置断点并在命名变量中包含要返回的值通常非常方便。
但是,我不会为单行而烦恼。

答案 3 :(得分:-1)

简短回答:它们是相同的,只有第一个(IMO)更具可读性。

更长的回答: 处理器对变量一无所知(并且最终由JVM编译的代码也将在处理器上运行),他们所知道的只是寄存器。当您返回一个值时,该值必须存储在寄存器中(让我们调用该寄存器返回)。所以,编译器并不关心你是否给了你的返回值一个名字,它只知道要返回你的计算值,它必须将它放入注册 return 并且&#39什么会发生。 a + b将被计算并存储在寄存器中。

只有非常非常愚蠢的编译器会在内存使用或速度方面有任何差异:可以想到编译器将第二个示例存储在两个寄存器中(首先它将结果计算为一个,然后复制该结果进入返回寄存器),而第一个只用于寄存器,但实际上并没有发生 - 所有编译器都足够聪明,可以确定你可以将结果直接存储在返回寄存器中。