[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 ก็ยังมีหลายตัวรอให้เข้าไปทดลองใช้งานกันครับ 😆