35

Sorry if this is a newbie question but I couldn't find an answer for this. Is it better to do this:

int result = number/number2;
return result;

or:

return number/number2;

I know integers use memory so I'm guessing it will slightly decrease performance? But on the other hand it makes stuff clearer, especially when the int/string is a long calculation.

Kalle Richter
  • 8,008
  • 26
  • 77
  • 177
SJ19
  • 1,933
  • 6
  • 35
  • 68
  • 13
    Unless you are truly trying to optimize performance, you should always prioritize readability. – Gnarlywhale Jul 30 '15 at 20:54
  • 1
    I'm guessing you wouldn't use a helper int with something as simple as number/number2? – SJ19 Jul 30 '15 at 21:07
  • 10
    Declaring a local variable helps with debugging when you want to inspect the return value before leaving the function. – Dave Jan 26 '16 at 15:58

3 Answers3

29

Edit: if, like me, you've been using more Kotlin than Java, it'd also be relevant to know that IntelliJ also has an inspection for this in 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.


There is actually a SonarQube rule inherited from PMD called Unnecessary Local Before Return that talks about this. It says:

Avoid unnecessarily creating local variables.

This rule was later replaced by SSLR rule Variables should not be declared and then immediately returned or thrown, which maintains the same position:

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.

And I totally agree with it.

IntelliJ (or at least Android Studio) also has a warning for this situation:

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.


I don't think performance is something to worry about at all in this situation. That being said, as @Clashsoft mentioned in his comment, the JIT will most likely inline the variable and you'll end up with the same result either way.

Community
  • 1
  • 1
Fred Porciúncula
  • 8,533
  • 3
  • 40
  • 57
  • 58
    I actually disagree with the SSLR rule. Often this makes methods much easier to debug, as there's a step in the debugger prior to returning from the method, where the result can be observed. The cost for that is a local variable on the stack....basically free to clean up. – Jared Jul 30 '15 at 21:59
  • 6
    You don't necessarily need a step before the `return` statement to check the value before it is returned while you're debugging. I believe it is more important to have a cleaner code than a slightly easier to debug one. Otherwise we would always have lots of local variables just to help us debugging each operation result. – Fred Porciúncula Jul 30 '15 at 22:03
  • 1
    @Jared Most debuggers allow you to evaluate the return statement when a breakpoint is hit, making the variable useless even for debugging. – JamesB Aug 02 '15 at 20:56
  • 25
    After playing around with the solutions provided here http://stackoverflow.com/questions/5010362/can-i-find-out-the-return-value-before-returning-while-debugging-in-intellij it's actually pretty clear that return value debugging of complex expressions is not really well usable. So having a return variable assigned makes debugging much much easier. Especially if you have to track down something from a multiple return chain. – Laazik Oct 21 '16 at 07:59
  • 5
    Agree with the benefits in debugging. Another benefit is naming the return value. If you follow law of demeter (not reaching way into your objects) and use clear variable names, a programmer should be able to derive the idea from the context (containing method name, name of the method or operation whose result you are returning), but this isn't always true as variable naming across contexts is hard. Plopping `Long.parseLong(price.getTotalValue())` into a variable like `finalCostAfterAdjusting` can add some helpful context to the programmer. – Sammaron Jul 16 '19 at 18:54
  • @Sammaron In this case your method should be called adjustCost() or something and then there’s no meed for the local variable. – Fred Porciúncula Jul 16 '19 at 20:04
  • @FredPorciuncula I agree -- in most cases, probably not necessary. But honestly, this is such a little evil if evil at all that in 99% of all contexts either solution is fine. To me, debugging and clarity benefits of local variables > extra line of code. And I want to feel like a rule breaker. – Sammaron Jul 17 '19 at 17:17
13

Choose the version that you think is more readable.

There are legitimate cases where the named variable improves readability. For example

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;
}

There are also cases where we need a variable in a different type from the return type. This affects type conversion and inference, making a significant semantic difference.

Foo foo()            vs.        Foo foo()
{                               {
                                    Bar bar = expr;
    return expr;                    return bar;
}                               }
ZhongYu
  • 19,446
  • 5
  • 33
  • 61
6

Compilers are usually smart enough to optimize this sort of thing as appropriate. See data-flow optimizations on Wikipedia.

In this case, it will probably need to allocate a temporary variable to store the result even if you don't specify one yourself.

Edit: Clashsoft is right about the bytecode compiler:

$ 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
}
Vlad
  • 18,195
  • 4
  • 41
  • 71