11個值得借鑒的Java?return寫法分享
前言
return
這個關(guān)鍵字,相信大家每天都在用。
它就像一把錘子,敲打著我們代碼里的每一個出口。
但捫心自問,我們真的把這把錘子用好了嗎?
今天,不想聊什么高深莫測的設(shè)計模式,也不敢妄稱“最佳實踐”。
只想結(jié)合自己這些年在項目摸爬滾打中踩過的一些坑、積累的一點心得,和大家分享一些關(guān)于 return
的、或許能讓我們的代碼更規(guī)范、更優(yōu)雅、更易讀的寫法。
權(quán)當拋磚引玉,希望能引發(fā)大家的一些思考。
耐心看完,你一定有所收獲。
1. 提前返回(衛(wèi)語句):讓主邏輯更清晰
這是最常見也是非常推薦的一種模式。
核心思想是:在方法開頭處理掉所有“異常”或“特殊”情況,讓方法的主體部分專注于核心邏輯。
反面教材 :
public void processData(Data data) { if (data != null) { if (data.isValid()) { if (checkPermission(data)) { // 核心邏輯開始... System.out.println("處理數(shù)據(jù):" + data.getContent()); // ... // 大量核心代碼嵌套在這里 // ... System.out.println("處理完成"); } else { System.out.println("權(quán)限不足"); } } else { System.out.println("數(shù)據(jù)無效"); } } else { System.out.println("數(shù)據(jù)為null"); } }
很難評,嵌套過深,核心邏輯被包裹在層層 if-else
中,可讀性太差。
推薦寫法 :
public void processData(Data data) { if (data == null) { System.out.println("數(shù)據(jù)為null"); return; // 提前返回 } if (!data.isValid()) { System.out.println("數(shù)據(jù)無效"); return; // 提前返回 } if (!checkPermission(data)) { System.out.println("權(quán)限不足"); return; // 提前返回 } // --- 核心邏輯開始 --- // 經(jīng)過前面的衛(wèi)語句檢查,這里的data一定是有效且有權(quán)限的 System.out.println("處理數(shù)據(jù):" + data.getContent()); // ... // 核心代碼不再嵌套,非常清晰 // ... System.out.println("處理完成"); }
通過提前 return
,避免了深層嵌套,讓主要的處理流程更加順暢,代碼邏輯一目了然。
配得上“優(yōu)雅”二字。
2. 避免 return 后的 else 塊
當 if
分支中包含 return
語句時,其后的代碼天然就是 else
的邏輯,無需顯式寫出 else
。
反面教材 :
public String getStatus(int code) { if (code == 0) { return "Success"; } else { // 其他邏輯 return "Error: " + getErrorMessage(code); } }
雖然沒錯,但 else
顯得有些多余,未免畫蛇添足。
推薦寫法 :
public String getStatus(int code) { if (code == 0) { return "Success"; } // 如果 code == 0,上面的 return 已經(jīng)退出方法了 // 能執(zhí)行到這里,說明 code != 0,天然就是 else 的邏輯 return "Error: " + getErrorMessage(code); }
代碼更簡潔,減少了一層不必要的縮進。
3. 簡化布爾返回
直接返回布爾表達式的結(jié)果,而不是使用 if-else
返回 true
或 false
。
反面教材 :
public boolean isEligible(User user) { if (user.getAge() >= 18 && user.isActive()) { return true; } else { return false; } }
點評:非常啰嗦。
推薦寫法 :
public boolean isEligible(User user) { return user.getAge() >= 18 && user.isActive(); }
一行搞定,清晰明了。
4. 減少不必要的臨時變量
如果一個變量僅僅是為了存儲即將 return
的值,可以考慮直接 return
表達式的結(jié)果。
反面教材:
public int calculateSum(int a, int b) { int sum = a + b; return sum; } public String getUserGreeting(User user) { String greeting = "Hello, " + user.getName(); return greeting; }
sum
和 greeting
變量并非必需。
推薦寫法 :
public int calculateSum(int a, int b) { return a + b; } public String getUserGreeting(User user) { // 如果 user.getName() 調(diào)用成本高或需要復(fù)用,臨時變量可能有意義 // 但在這個簡單場景下,直接返回更簡潔 return "Hello, " + user.getName(); }
更直接。
但注意,如果表達式復(fù)雜或計算結(jié)果需要復(fù)用,還是考慮使用臨時變量,可以提高可讀性或效率,需要權(quán)衡。
5. 巧用三元運算符
對于簡單的二選一返回邏輯,三元運算符 ?:
是 if-else
的簡潔替代。
反面教材 :
public String getLevel(int score) { String level; if (score >= 60) { level = "Pass"; } else { level = "Fail"; } return level; }
推薦寫法 :
public String getLevel(int score) { return score >= 60 ? "Pass" : "Fail"; }
一行代碼,清晰表達了條件選擇。
但是千萬注意不要濫用,過分嵌套的三元運算符會降低可讀性。
6. 返回空集合而非 null
方法約定返回集合類型(List, Set, Map等)時,如果沒有數(shù)據(jù),應(yīng)返回空集合而不是 null
。
這可以避免調(diào)用方不必要的 null
檢查。
反面教材 :
public List<String> getUsers(String department) { List<String> users = findUsersByDepartment(department); if (users.isEmpty()) { // 或者 users == null return null; // 調(diào)用方需要檢查 null ! } return users; }
推薦寫法 :
import java.util.Collections; import java.util.List; public List<String> getUsers(String department) { List<String> users = findUsersByDepartment(department); // 假設(shè) findUsersByDepartment 可能返回 null 或空 List if (users == null || users.isEmpty()) { return Collections.emptyList(); // 返回不可變的空列表 } // 或者更好的是,確保 findUsersByDepartment 內(nèi)部就返回空列表而不是 null return users; } // 調(diào)用方代碼,無需擔(dān)心 NullPointerException List<String> userList = service.getUsers("IT"); for (String user : userList) { // 直接遍歷,安全 System.out.println(user); }
調(diào)用方代碼更健壯、簡潔,符合“防御性編程”的原則。
7. 利用 Optional 優(yōu)雅處理可能缺失的值
當方法可能返回一個值,也可能什么都不返回時,使用 Optional<T>
作為返回類型比返回 null
更能明確表達這種可能性,并引導(dǎo)調(diào)用方正確處理。
反面教材 :
public User findUserById(String id) { // ... 查詢邏輯 ... if (found) { return user; } else { return null; // 調(diào)用方必須檢查 null } } // 調(diào)用方 User user = findUserById("123"); if (user != null) { // 繁瑣的 null 檢查 System.out.println(user.getName()); }
推薦寫法 :
import java.util.Optional; public Optional<User> findUserById(String id) { // ... 查詢邏輯 ... if (found) { return Optional.of(user); } else { return Optional.empty(); } } // 調(diào)用方 findUserById("123") .ifPresent(user -> System.out.println(user.getName())); // 清晰地處理存在的情況 // 或者提供默認值 String userName = findUserById("123") .map(User::getName) .orElse("Unknown User");
Optional
強制調(diào)用者思考值不存在的情況,并通過鏈式調(diào)用提供了更流暢的處理方式,減少空指針風(fēng)險。
但是Java的Optional
非常頭疼,如果使用時不加注意,本應(yīng)返回Optional
的方法,返回了null,反而會增加負擔(dān),因此團隊的開發(fā)規(guī)范至關(guān)重要。
8. 循環(huán)中的提前返回
在循環(huán)中查找元素或滿足某個條件時,一旦找到或滿足,應(yīng)立即 return
,避免不必要的后續(xù)迭代。
反面教材 :
public Product findProductByName(List<Product> products, String name) { Product foundProduct = null; for (Product product : products) { if (product.getName().equals(name)) { foundProduct = product; break; // 找到后跳出循環(huán) } } // 循環(huán)結(jié)束后再返回 return foundProduct; }
需要一個額外的 foundProduct
變量,并且在循環(huán)外返回。
浪費性能。
推薦寫法 :
public Product findProductByName(List<Product> products, String name) { for (Product product : products) { if (product.getName().equals(name)) { return product; // 一旦找到,立即返回 } } // 循環(huán)正常結(jié)束,說明沒找到 return null; // 或者 Optional.empty() }
邏輯更直接,代碼更緊湊。
9. 利用 switch 表達式(Java 14+)
現(xiàn)在Java的 switch
表達式可以直接返回值,使得基于多分支選擇的返回更加簡潔。
反面教材 (傳統(tǒng) switch 語句):
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; }
推薦寫法 (使用 switch 表達式):
public String getWeekdayType(DayOfWeek day) { return switch (day) { case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Workday"; case SATURDAY, SUNDAY -> "Weekend"; // default 分支通常是必需的,除非覆蓋了所有枚舉常量 // 如果邏輯確定上面的 case 已經(jīng)覆蓋所有情況,可以不寫 default, // 但如果傳入未覆蓋的值會拋異常。 // 或者明確處理: // default -> throw new IllegalArgumentException("Invalid day: " + day); }; }
代碼量顯著減少,->
語法更直觀,且 switch
表達式要求覆蓋所有情況(或有 default
),更安全。
10. 返回更有意義的類型(枚舉或自定義對象)
避免使用魔法數(shù)字或含義模糊的字符串作為返回碼,應(yīng)返回定義清晰的枚舉或包含狀態(tài)和信息的自定義結(jié)果對象。
反面教材 :
public int processOrder(Order order) { if (order == null) return -1; // -1 代表失敗 if (!checkInventory(order)) return 1; // 1 代表庫存不足 // ... 處理 ... if (!paymentSuccess(order)) return 2; // 2 代表支付失敗 return 0; // 0 代表成功 } // 調(diào)用方 int resultCode = processOrder(myOrder); if (resultCode == 0) { ... } else if (resultCode == 1) { ... } // 難以理解和維護
推薦寫法 :
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; // ... 處理 ... if (!paymentSuccess(order)) return OrderStatus.FAILED_PAYMENT; return OrderStatus.SUCCESS; } // 調(diào)用方 OrderStatus status = processOrder(myOrder); if (status == OrderStatus.SUCCESS) { ... } else if (status == OrderStatus.FAILED_INVENTORY) { ... } // 清晰易懂
返回類型本身就攜帶了業(yè)務(wù)含義,代碼自解釋,更易于維護和擴展。
11. 注意 finally 塊中的 return(陷阱!)
盡量避免在 finally
塊中使用 return
。
它會覆蓋 try
或 catch
塊中的 return
或拋出的異常,可能導(dǎo)致非預(yù)期的行為和難以追蹤的 Bug。
反面教材 (極不推薦):
public int trickyReturn() { try { System.out.println("Trying..."); // 假設(shè)這里發(fā)生異?;蛘7祷?1 // throw new RuntimeException("Oops!"); return 1; } catch (Exception e) { System.out.println("Caught exception"); return 2; // 試圖在 catch 中返回 2 } finally { System.out.println("Finally block"); return 3; // finally 中的 return 會覆蓋前面的所有返回/異常! } // 這個方法最終會返回 3,即使 try 或 catch 中有 return 或拋出異常 }
finally
的主要目的是資源清理(如關(guān)閉流、釋放鎖),而不是返回值。
在這里 return
會讓程序行為變得詭異。
推薦寫法 :
public int cleanReturn() { int result = -1; // 默認值或錯誤碼 Connection conn = null; try { conn = getConnection(); // ... 使用 conn 操作 ... result = 1; // 操作成功 return result; // 在 try 中返回 } catch (SQLException e) { System.err.println("Database error: " + e.getMessage()); result = -2; // 數(shù)據(jù)庫錯誤碼 return result; // 在 catch 中返回 } finally { // 只做清理工作 if (conn != null) { try { conn.close(); System.out.println("Connection closed."); } catch (SQLException e) { System.err.println("Failed to close connection: " + e.getMessage()); } } // 不要在 finally 中 return } }
finally
專注于它的本職工作——資源清理,讓返回值邏輯在 try
和 catch
中清晰地處理。
結(jié)尾
return
雖小,五臟俱全。
一切的目的都是讓代碼更加優(yōu)雅,邏輯更加清晰。
這些并非什么高深的理論,更多的是在日常寫代碼時,對可讀性、簡潔性和健壯性的追求。
到此這篇關(guān)于11個值得借鑒的Java return寫法分享的文章就介紹到這了,更多相關(guān)Java return寫法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Java如何實現(xiàn)與JS相同的Des加解密算法
這篇文章主要介紹了如何在Java中實現(xiàn)與JavaScript相同的DES(Data Encryption Standard)加解密算法,確保在兩個平臺之間可以無縫地傳遞加密信息,希望對大家有一定的幫助2025-04-04Springboot整合spring-boot-starter-data-elasticsearch的過程
本文詳細介紹了Springboot整合spring-boot-starter-data-elasticsearch的過程,包括版本要求、依賴添加、實體類添加、索引的名稱、分片、副本設(shè)置等,同時,還介紹了如何使用ElasticsearchRepository類進行增刪改查操作2024-10-10zookeeper實戰(zhàn)之實現(xiàn)分布式鎖的方法
Zookeeper實現(xiàn)分布式鎖比Redis簡單,Zookeeper有一個特性,多個線程在Zookeeper里創(chuàng)建同一個節(jié)點時,只有一個線程執(zhí)行成功,Zookeeper主要是利用臨時有序節(jié)點這一特性實現(xiàn)分布式鎖,感興趣的朋友跟隨小編一起學(xué)習(xí)吧2022-11-11SpringMVC將請求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換為JSON格式的幾種方式
這篇文章主要給大家介紹餓了SpringMVC將請求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換為JSON格式的幾種方式,文中通過代碼示例和圖文結(jié)合給大家介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下2023-11-11java實現(xiàn)數(shù)字轉(zhuǎn)大寫的方法
這篇文章主要介紹了 java實現(xiàn)數(shù)字轉(zhuǎn)大寫的方法的相關(guān)資料,希望通過本文能幫助到大家,讓大家實現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫
這篇文章主要介紹了springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07Java實現(xiàn)快速排序算法(Quicktsort)
這篇文章主要介紹了Java實現(xiàn)快速排序算法(Quicktsort),有需要的朋友可以參考一下2013-12-12