return 语句之前的局部变量,重要吗?

Local variables before return statements, does it matter?

抱歉,如果这是一个新手问题,但我找不到这个问题的答案。 这样做更好吗:

int result = number/number2;
return result;

或:

return number/number2;

我知道整数使用内存所以我猜它会稍微降低性能?但另一方面,它使事情变得更清晰,尤其是当 int/string 是一个长计算时。

编辑: 如果像我一样,您使用的 Kotlin 多于 Java,知道 IntelliJ 也有检查也很重要对于 Kotlin 中的这个:

Variable used only in following return and should be inlined

This inspection reports local variables either used only in the very next return statement or exact copies of other variables. In both cases it's better to inline such a variable.


实际上有一个继承自 PMD 的 SonarQube 规则,称为 Unnecessary Local Before Return,它谈到了这一点。它说:

Avoid unnecessarily creating local variables.

此规则是 later replaced by SSLR rule Variables should not be declared and then immediately returned or thrown,保持相同的位置:

Declaring a variable only to immediately return or throw it is a bad practice. Some developers argue that the practice improves code readability, because it enables them to explicitly name what is being returned. However, this variable is an internal implementation detail that is not exposed to the callers of the method. The method name should be sufficient for callers to know exactly what will be returned.

我完全同意。

IntelliJ(或者至少AndroidStudio)对于这种情况也有警告:

Variable used only in following return and can be inlined

This inspection reports local variables either used only in the very next return or exact copies of other variables. In both cases it's better to inline such a variable.


我认为在这种情况下根本不需要担心性能。话虽这么说,正如@Clashsoft 在他的评论中提到的那样,JIT 很可能会内联变量,无论哪种方式,您最终都会得到相同的结果。

编译器通常足够聪明,可以适当地优化这类事情。请参阅维基百科上的 data-flow optimizations

在这种情况下,即使您没有自己指定,也可能需要分配一个临时变量来存储结果。

编辑:Clashsoft 关于字节码编译器的说法是正确的:

$ cat a.java
class a {
   public static int a(int x, int y) {
     return x / y;
   }

   public static int b(int x, int y) {
     int r = x/y;
     return r;
   }

   public static int c(int x, int y) {
     final int r = x/y;
     return r;
   }
}
$ javap -c a
Compiled from "a.java"
class a {
  a();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static int a(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: idiv
       3: ireturn

  public static int b(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: idiv
       3: istore_2
       4: iload_2
       5: ireturn

  public static int c(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: idiv
       3: istore_2
       4: iload_2
       5: ireturn
}

选择认为可读性更好的版本。

在某些合理的情况下,命名变量会提高可读性。例如

public String encrypt(String plainString)
{
    byte[] plainBytes      = plainString.getBytes(StandardCharsets.UTF_8);
    byte[] hashPlainBytes  = enhash( plainBytes, 4 );
    byte[] encryptedBytes  = doAes128(Cipher.ENCRYPT_MODE , hashPlainBytes );
    String encryptedBase64 = Base64.getEncoder().withoutPadding().encodeToString(encryptedBytes);
    return encryptedBase64;
}

public String decrypt(String encryptedBase64)
{
    byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64);
    byte[] hashPlainBytes = doAes128(Cipher.DECRYPT_MODE , encryptedBytes );
    byte[] plainBytes     = dehash( hashPlainBytes, 4 );
    String plainString = new String(plainBytes, StandardCharsets.UTF_8);
    return plainString;
}

在某些情况下,我们需要一个不同于 return 类型的变量。这会影响类型转换和推理,从而产生显着的语义差异。

Foo foo()            vs.        Foo foo()
{                               {
                                    Bar bar = expr;
    return expr;                    return bar;
}                               }