Preface
return
I believe everyone uses this keyword every day.
It's like a hammer, hitting every exit in our code.
But ask yourself, have we really used this hammer?
Today, I don’t want to talk about the unfathomable design model, nor dare to call it “best practice”.
I just want to share some of the pitfalls I have stepped on in the project over the years and some of my accumulated experiences, and I will share with you some of my concerns.return
, perhaps making our code more standardized, elegant and readable.
Just like to throw a brick and attract jade, I hope it can trigger some thoughts from everyone.
After reading patiently, you will definitely gain something.
1. Return in advance (Defense statement): Make the main logic clearer
This is the most common and highly recommended model.
The core idea is: deal with all "exceptions" or "special" situations at the beginning of the method, so that the main part of the method can focus on the core logic.
Reverse textbook:
public void processData(Data data) { if (data != null) { if (()) { if (checkPermission(data)) { // The core logic begins... ("Processing data:" + ()); // ... // A lot of core code is nested here // ... ("Processing is completed"); } else { ("Insufficient permissions"); } } else { ("Invalid data"); } } else { ("Data is null"); } }
It's hard to evaluate, too deep nesting, core logic is wrapped in layersif-else
The readability is too poor.
Recommended writing method:
public void processData(Data data) { if (data == null) { ("Data is null"); return; // Return in advance } if (!()) { ("Invalid data"); return; // Return in advance } if (!checkPermission(data)) { ("Insufficient permissions"); return; // Return in advance } // --- The core logic begins --- // After the previous ward statement check, the data here must be valid and authorized ("Processing data:" + ()); // ... // The core code is no longer nested, very clear // ... ("Processing is completed"); }
Byreturn
, avoid deep nesting, make the main processing flow smoother and the code logic is clear at a glance.
It deserves the word "elegance".
2. Avoid the else block after return
whenif
Included in the branchreturn
When the statement is, the subsequent code is naturallyelse
The logic ofelse
。
Reverse textbook:
public String getStatus(int code) { if (code == 0) { return "Success"; } else { // Other logic return "Error: " + getErrorMessage(code); } }
Although it is true,else
It seems a bit redundant and adds to the point.
Recommended writing method:
public String getStatus(int code) { if (code == 0) { return "Success"; } // If code == 0, the above return has exited the method // If you can execute it here, it means that code != 0 is naturally the logic of else return "Error: " + getErrorMessage(code); }
The code is more concise and reduces an unnecessary layer of indentation.
3. Simplify boolean return
Returns the result of a boolean expression directly, rather than usingif-else
returntrue
orfalse
。
Reverse textbook:
public boolean isEligible(User user) { if (() >= 18 && ()) { return true; } else { return false; } }
Comment: Very long-winded.
Recommended writing method:
public boolean isEligible(User user) { return () >= 18 && (); }
The whole line is done, it’s clear.
4. Reduce unnecessary temporary variables
If a variable is just to store the nextreturn
The value ofreturn
The result of the expression.
Reverse textbook:
public int calculateSum(int a, int b) { int sum = a + b; return sum; } public String getUserGreeting(User user) { String greeting = "Hello, " + (); return greeting; }
sum
andgreeting
Variables are not required.
Recommended writing method:
public int calculateSum(int a, int b) { return a + b; } public String getUserGreeting(User user) { // If () call is expensive or requires reuse, temporary variables may make sense // But in this simple scenario, it is simpler to go straight to the simpler return "Hello, " + (); }
More direct.
But note that if the expression is complex or the calculation results need to be reused, or if the use of temporary variables can be improved, it requires trade-offs.
5. Use the ternary operator skillfully
For simple two-choice return logic, ternary operator?:
yesif-else
a simple alternative.
Reverse textbook:
public String getLevel(int score) { String level; if (score >= 60) { level = "Pass"; } else { level = "Fail"; } return level; }
Recommended writing method:
public String getLevel(int score) { return score >= 60 ? "Pass" : "Fail"; }
A line of code clearly expresses the conditional selection.
But be careful not to abuse it, as excessively nested ternary operators will reduce readability.
6. Return an empty set instead of null
When the method convention returns the set type (List, Set, Map, etc.), if there is no data, an empty set should be returned instead ofnull
。
This avoids unnecessarynull
examine.
Reverse textbook:
public List<String> getUsers(String department) { List<String> users = findUsersByDepartment(department); if (()) { // Or users == null return null; // The caller needs to check null! } return users; }
Recommended writing method:
import ; import ; public List<String> getUsers(String department) { List<String> users = findUsersByDepartment(department); // Assume that findUsersByDepartment may return null or empty List if (users == null || ()) { return (); // Return an immutable empty list } // Or better yet, make sure that findUsersByDepartment returns an empty list instead of null return users; } // Caller code, no need to worry about NullPointerExceptionList<String> userList = ("IT"); for (String user : userList) { // Direct traversal, safe (user); }
The caller code is more robust and concise, and conforms to the principle of "defensive programming".
7. Use Optional to elegantly handle possible missing values
When a method may return a value or may return nothing, useOptional<T>
Return as return type rationull
It can better express this possibility and guide the caller to handle it correctly.
Reverse textbook:
public User findUserById(String id) { // ... Query logic ... if (found) { return user; } else { return null; // The caller must check null } } // CallerUser user = findUserById("123"); if (user != null) { // tedious null check (()); }
Recommended writing method:
import ; public Optional<User> findUserById(String id) { // ... Query logic ... if (found) { return (user); } else { return (); } } // CallerfindUserById("123") .ifPresent(user -> (())); // Clearly handle existing situations // Or provide default valuesString userName = findUserById("123") .map(User::getName) .orElse("Unknown User");
Optional
Force the caller to think about the situation where the value does not exist, and provides a smoother way of processing through chain calls to reduce the risk of null pointers.
But Java'sOptional
Very headache, if you don't pay attention to it, you should return itOptional
The method of null will increase the burden instead, so the team's development specifications are crucial.
8. Early return in the loop
When looking for an element in a loop or satisfying a certain condition, it should be immediatelyreturn
, avoid unnecessary subsequent iterations.
Reverse textbook:
public Product findProductByName(List<Product> products, String name) { Product foundProduct = null; for (Product product : products) { if (().equals(name)) { foundProduct = product; break; // Loop out of the loop after finding } } // Return after the loop is over return foundProduct; }
Need an extrafoundProduct
variable, and returned outside the loop.
Waste of performance.
Recommended writing method:
public Product findProductByName(List<Product> products, String name) { for (Product product : products) { if (().equals(name)) { return product; // Once found, return immediately } } // The loop ends normally, which means that no found return null; // or ()}
The logic is more direct and the code is more compact.
9. Use switch expressions (Java 14+)
Java nowswitch
Expressions can directly return values, making returns based on multi-branch selection more concise.
Negative textbook (traditional switch statement):
public String getWeekdayType(DayOfWeek day) { String type; switch (day) { case MONDAY: case TUESDAY: case WEDNESDAY: case THURSDAY: case FRIDAY: type = "Workday"; break; case SATURDAY: case SUNDAY: type = "Weekend"; break; default: throw new IllegalArgumentException("Invalid day: " + day); } return type; }
Recommended writing method (using switch expression):
public String getWeekdayType(DayOfWeek day) { return switch (day) { case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Workday"; case SATURDAY, SUNDAY -> "Weekend"; // default branch is usually required unless all enum constants are covered // If the logic determines that the above case has covered all cases, you can not write default. // But if an uncovered value is passed in, an exception will be thrown. // Or explicitly handle: // default -> throw new IllegalArgumentException("Invalid day: " + day); }; }
The code volume is significantly reduced.->
The syntax is more intuitive, andswitch
The expression requires that all cases be covered (ordefault
), safer.
10. Returns a more meaningful type (enum or custom object)
Avoid using magic numbers or fuzzy strings as return codes, and should return clear-defined enumerations or custom result objects containing state and information.
Reverse textbook:
public int processOrder(Order order) { if (order == null) return -1; // -1 means failure if (!checkInventory(order)) return 1; // 1 means insufficient inventory // ... deal with ... if (!paymentSuccess(order)) return 2; // 2 means payment failed return 0; // 0 means success} // Callerint resultCode = processOrder(myOrder); if (resultCode == 0) { ... } else if (resultCode == 1) { ... } // Difficult to understand and maintain
Recommended writing method:
public enum OrderStatus { SUCCESS, FAILED_NULL_ORDER, FAILED_INVENTORY, FAILED_PAYMENT } public OrderStatus processOrder(Order order) { if (order == null) return OrderStatus.FAILED_NULL_ORDER; if (!checkInventory(order)) return OrderStatus.FAILED_INVENTORY; // ... deal with ... if (!paymentSuccess(order)) return OrderStatus.FAILED_PAYMENT; return ; } // CallerOrderStatus status = processOrder(myOrder); if (status == ) { ... } else if (status == OrderStatus.FAILED_INVENTORY) { ... } // Clear and easy to understand
The return type itself carries the business meaning, the code is self-interpreted, making it easier to maintain and expand.
11. Note the return (trap!) in the finally block
Try to avoidfinally
Used in blocksreturn
。
It will covertry
orcatch
in blockreturn
or thrown exceptions can lead to unexpected behavior and difficult to trace bugs.
Reverse textbook (extremely not recommended):
public int trickyReturn() { try { ("Trying..."); // Suppose an exception occurs here or returns 1 normally // throw new RuntimeException("Oops!"); return 1; } catch (Exception e) { ("Caught exception"); return 2; // Try to return 2 in catch } finally { ("Finally block"); return 3; // The return in finally will overwrite all previous returns/exceptions! } // This method will eventually return 3, even if there is a return or an exception is thrown in try or catch}
finally
The main purpose is resource cleaning (such as closing the stream, releasing the lock), rather than returning the value.
Herereturn
It will make the program behavior weird.
Recommended writing method:
public int cleanReturn() { int result = -1; // Default value or error code Connection conn = null; try { conn = getConnection(); // ... Use conn to operate... result = 1; // Operation is successful return result; // Return in try } catch (SQLException e) { ("Database error: " + ()); result = -2; // Database error code return result; // Return in catch } finally { // Only clean up if (conn != null) { try { (); ("Connection closed."); } catch (SQLException e) { ("Failed to close connection: " + ()); } } // Don't return in finally } }
finally
Focus on its job - resource cleaning, let the return value logic betry
andcatch
clear processing.
Ending
return
Although small, it has all the internal organs.
The purpose of all is to make the code more elegant and the logic clearer.
These are not profound theories, but more of the pursuit of readability, simplicity and robustness when writing code in daily life.
This is the end of this article about 11 Java return writing methods that are worth learning from. For more related Java return writing content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!