Local variables before return statements, does it matter?

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.


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