[Java] try-with-resouces กับการคืนทรัพยากรบน Java 7
Java 7 มี syntax ที่เราอาจไม่ได้รู้สึกตัวว่ามันมีอยู่ คราวนี้เราก็จะมาทำความรู้จัก try-with-resources ที่เป็นตัวช่วยสำคัญในการยุ่งกับ resources ต่าง ๆ เช่น การเชื่อมต่อฐานข้อมูล(Database connection) การเขียน-อ่านไฟล์ เป็นต้น
ปกติแล้ว การเขียนโปรแกรมขั้นพื้นฐาน ก็เราได้รู้จักการใช้งาน object ซึ่งก็จะมี lifetime ของตัวมันเองแต่ก่อน การยุ่งกับ resources เราจำเป็นจะต้องเขียนเปิด-ปิดการใช้งานเอง จุดนี้ try-with-resources จะเข้ามาช่วยให้เราเขียนโค้ดง่ายขึ้น
การเชื่อมต่อฐานข้อมูลโดยไม่ใช้
ถ้าเขียนตามจินตนาการขั้นแรกสุด
ปกติแล้ว การเขียนโปรแกรมขั้นพื้นฐาน ก็เราได้รู้จักการใช้งาน object ซึ่งก็จะมี lifetime ของตัวมันเองแต่ก่อน การยุ่งกับ resources เราจำเป็นจะต้องเขียนเปิด-ปิดการใช้งานเอง จุดนี้ try-with-resources จะเข้ามาช่วยให้เราเขียนโค้ดง่ายขึ้น
การเชื่อมต่อฐานข้อมูลโดยไม่ใช้ try-with-resourcs
ถ้าเขียนตามจินตนาการขั้นแรกสุด- เปิดใช้งาน resources
- อย่าลืมปิดเมื่อใช้เสร็จ
Connection con = getConnection(); ... .. . con.close()แต่ แต่ แต่ ! การเรียกใช้งาน resources ส่วนใหญ่จะพ่วงกันมาหลายตัว และจะบังคับให้เราเขียน try-catch เพื่อจัดการบางอย่างเมื่อเกิดปัญหาขึ้น ซึ่งเราจะต้องตามปิด resources ทั้งเคสที่ทำงานถูกต้องและไม่ถูกต้องของทุกตัว
Connection con = null; Statement stm = null; ResultSet rs = null; try { String sql = "SELECT * FROM UserAccount"; con = getConnection(); stm = con.createStatement(); rs = stm.executeQuery(sql); while(rs.next()) { rs.getString("USERNAME"); rs.getString("EMAIL"); } } catch (SQLException sqle) { } finally { closeResource(rs, stm, con); }วิธีที่ดีที่สุดของแบบเก่าคือ การทำเป็น method และเรียกใน finally ของ try-catch block เนื่องจากจะทำงานทุกกรณี แต่ถึงอย่างนั้นก็เถอะ มันก็ให้ความรู้สึกแหม่ง ๆ ลองดูใน method ตัวอย่างครับ
public static void closeResource(ResultSet rs, Statement stm, Connection con) { if (rs != null) { try { rs.close(); } catch (SQLException e) {} } if (stm != null) { try { stm.close(); } catch (SQLException e) {} } if (con != null) { try { con.close(); } catch (SQLException e) {} } }
การเชื่อมต่อฐานข้อมูลโดยใช้ try-with-resources
try-with-resources จะมาช่วยเราจัดการกับทรัพยากรที่จำเป็นต้องปิด โดยใช้ syntax ของ try และเพิ่มความสามารถเข้าไปtry (/* resources declaration */ ) { /* statement block */ }เราสามารถใช้งานโดยไม่ต้องคิดเรื่องจะปิดจะเปิดอีกต่อไปแล้ว หลังจากสิ้นสุดการทำงานภายใต้ try-with-resources ก็จะถือว่าเป็นการสิ้นสุดการใช้งาน resources เช่นกัน และจะเป็นการปิดการเชื่อมต่อโดยอัตโนมัติ ไม่จำเป็นต้องเขียน close เองอีกต่อไป ลองดูตัวอย่างเต็ม ๆ กันดูครับ
String sql = "SELECT * FROM UserAccount"; try (Connection con = getConnection(); Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery(sql);) { while(rs.next()) { rs.getString("USERNAME"); rs.getString("EMAIL"); } } catch (SQLException sqle) { }จากโค้ดก่อนหน้านี้ เมื่อนำมาเปรียบเทียบกันก็ดูสั้นกว่ามาก แต่ไม่ใช่ทุก Class ที่จะเขียนให้เป็น try-with-resources ได้ ซึ่งก็มีข้อควรจำนิด ๆ หน่อย ๆ
- JDK 7+
- เป็น Class ที่ inherit มาจาก AutoCloseable
- ในวงเล็บต้องเป็นการประกาศ resources เท่านั้น ไม่สามารถเติม statement อื่นได้
- สามารถเขียน try เปล่า ๆ ได้หรือเพิ่ม catch ได้เมื่อจำเป็น (ถ้า try-catch จะไม่สามารถเขียน try ลอย ๆ ได้)
AutoCloseable เป็น super Class / super Interface ของหลาย ๆ ตัวที่ผมยังไม่ได้พูดถึง ซึ่งทุกตัวสามารถใช้งานกับ try-with-resources ได้ นอกเหนือจากเรื่องของ database connection ก็ยังมีหลายตัวรอให้เข้าไปทดลองใช้งานกันครับ 😆